<!doctype html>
<html>
<head>
<meta charset='UTF-8'><meta name='viewport' content='width=device-width initial-scale=1'>
<title>Anguluar.md</title><link href='https://fonts.googleapis.com/css?family=PT+Serif:400,400italic,700,700italic&subset=latin,cyrillic-ext,cyrillic,latin-ext' rel='stylesheet' type='text/css'><style type='text/css'>html, body {overflow-x: initial !important;}.CodeMirror { height: auto; }
.CodeMirror-scroll { overflow-y: hidden; overflow-x: auto; }
.CodeMirror-lines { padding: 4px 0px; }
.CodeMirror pre { }
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { background-color: white; }
.CodeMirror-gutters { border-right: 1px solid rgb(221, 221, 221); background-color: rgb(247, 247, 247); white-space: nowrap; }
.CodeMirror-linenumbers { }
.CodeMirror-linenumber { padding: 0px 3px 0px 5px; text-align: right; color: rgb(153, 153, 153); }
.CodeMirror div.CodeMirror-cursor { border-left: 1px solid black; z-index: 3; }
.CodeMirror div.CodeMirror-secondarycursor { border-left: 1px solid silver; }
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor { width: auto; border: 0px; background: rgb(119, 238, 119); z-index: 1; }
.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite { }
.cm-tab { display: inline-block; }
.cm-s-typora-default .cm-header, .cm-s-typora-default .cm-property { color: rgb(217, 79, 138); }
.cm-s-typora-default pre.cm-header1:not(.cm-atom) :not(.cm-overlay) { font-size: 2rem; line-height: 2rem; }
.cm-s-typora-default pre.cm-header2:not(.cm-atom) :not(.cm-overlay) { font-size: 1.4rem; line-height: 1.4rem; }
.cm-s-typora-default .cm-atom, .cm-s-typora-default .cm-number { color: rgb(149, 132, 134); }
.cm-s-typora-default .cm-table-row, .cm-s-typora-default .cm-block-start { font-family: monospace; }
.cm-s-typora-default .cm-comment, .cm-s-typora-default .cm-code { color: rgb(74, 90, 159); font-family: monospace; }
.cm-s-typora-default .cm-tag { color: rgb(169, 68, 66); }
.cm-s-typora-default .cm-string { color: rgb(126, 134, 169); }
.cm-s-typora-default .cm-link { color: rgb(196, 122, 15); text-decoration: underline; }
.cm-s-typora-default .cm-variable-2, .cm-s-typora-default .cm-variable-1 { color: inherit; }
.cm-s-typora-default .cm-overlay { font-size: 1rem; font-family: monospace; }
.CodeMirror.cm-s-typora-default div.CodeMirror-cursor { border-left: 3px solid rgb(228, 98, 154); }
.cm-s-typora-default .CodeMirror-activeline-background { left: -60px; right: -30px; background: rgba(204, 204, 204, 0.2); }
.cm-s-typora-default .CodeMirror-gutters { border-right: none; background-color: inherit; }
.cm-s-typora-default .cm-trailing-space-new-line::after, .cm-startspace::after, .cm-starttab .cm-tab::after { content: "•"; position: absolute; left: 0px; opacity: 0; font-family: LetterGothicStd, monospace; }
.os-windows .cm-startspace::after, .os-windows .cm-starttab .cm-tab::after { left: -0.1em; }
.cm-starttab .cm-tab::after { content: " "; }
.cm-startspace, .cm-tab, .cm-starttab, .cm-trailing-space-a, .cm-trailing-space-b, .cm-trailing-space-new-line { font-family: monospace; position: relative; }
.cm-s-typora-default .cm-trailing-space-new-line::after { content: "↓"; opacity: 0.3; }
.cm-s-inner .cm-keyword { color: rgb(119, 0, 136); }
.cm-s-inner .cm-atom, .cm-s-inner.cm-atom { color: rgb(34, 17, 153); }
.cm-s-inner .cm-number { color: rgb(17, 102, 68); }
.cm-s-inner .cm-def { color: rgb(0, 0, 255); }
.cm-s-inner .cm-variable { color: black; }
.cm-s-inner .cm-variable-2 { color: rgb(0, 85, 170); }
.cm-s-inner .cm-variable-3 { color: rgb(0, 136, 85); }
.cm-s-inner .cm-property { color: black; }
.cm-s-inner .cm-operator { color: rgb(152, 26, 26); }
.cm-s-inner .cm-comment, .cm-s-inner.cm-comment { color: rgb(170, 85, 0); }
.cm-s-inner .cm-string { color: rgb(170, 17, 17); }
.cm-s-inner .cm-string-2 { color: rgb(255, 85, 0); }
.cm-s-inner .cm-meta { color: rgb(85, 85, 85); }
.cm-s-inner .cm-qualifier { color: rgb(85, 85, 85); }
.cm-s-inner .cm-builtin { color: rgb(51, 0, 170); }
.cm-s-inner .cm-bracket { color: rgb(153, 153, 119); }
.cm-s-inner .cm-tag { color: rgb(17, 119, 0); }
.cm-s-inner .cm-attribute { color: rgb(0, 0, 204); }
.cm-s-inner .cm-header, .cm-s-inner.cm-header { color: blue; }
.cm-s-inner .cm-quote, .cm-s-inner.cm-quote { color: rgb(0, 153, 0); }
.cm-s-inner .cm-hr, .cm-s-inner.cm-hr { color: rgb(153, 153, 153); }
.cm-s-inner .cm-link, .cm-s-inner.cm-link { color: rgb(0, 0, 204); }
.cm-negative { color: rgb(221, 68, 68); }
.cm-positive { color: rgb(34, 153, 34); }
.cm-header, .cm-strong { font-weight: bold; }
.cm-del { text-decoration: line-through; }
.cm-em { font-style: italic; }
.cm-link { text-decoration: underline; }
.cm-error { color: rgb(255, 0, 0); }
.cm-invalidchar { color: rgb(255, 0, 0); }
.cm-constant { color: rgb(38, 139, 210); }
.cm-defined { color: rgb(181, 137, 0); }
div.CodeMirror span.CodeMirror-matchingbracket { color: rgb(0, 255, 0); }
div.CodeMirror span.CodeMirror-nonmatchingbracket { color: rgb(255, 34, 34); }
.cm-s-inner .CodeMirror-activeline-background { background: inherit; }
.CodeMirror { position: relative; overflow: hidden; }
.CodeMirror-scroll { margin-bottom: -30px; margin-right: -30px; padding-bottom: 30px; padding-right: 30px; height: 100%; outline: none; position: relative; box-sizing: content-box; }
.CodeMirror-sizer { position: relative; }
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { position: absolute; z-index: 6; display: none; }
.CodeMirror-vscrollbar { right: 0px; top: 0px; overflow-x: hidden; overflow-y: scroll; }
.CodeMirror-hscrollbar { bottom: 0px; left: 0px; overflow-y: hidden; overflow-x: scroll; }
.CodeMirror-scrollbar-filler { right: 0px; bottom: 0px; }
.CodeMirror-gutter-filler { left: 0px; bottom: 0px; }
.CodeMirror-gutters { position: absolute; left: 0px; top: 0px; padding-bottom: 30px; z-index: 3; }
.CodeMirror-gutter { white-space: normal; height: 100%; box-sizing: content-box; padding-bottom: 30px; margin-bottom: -32px; display: inline-block; }
.CodeMirror-gutter-elt { position: absolute; cursor: default; z-index: 4; }
.CodeMirror-lines { cursor: text; }
.CodeMirror pre { border-radius: 0px; border-width: 0px; background: transparent; font-family: inherit; font-size: inherit; margin: 0px; white-space: pre; word-wrap: normal; color: inherit; z-index: 2; position: relative; overflow: visible; }
.CodeMirror-wrap pre { word-wrap: break-word; white-space: pre-wrap; word-break: normal; }
.CodeMirror-code pre { border-right: 30px solid transparent; width: fit-content; }
.CodeMirror-wrap .CodeMirror-code pre { border-right: none; width: auto; }
.CodeMirror-linebackground { position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; z-index: 0; }
.CodeMirror-linewidget { position: relative; z-index: 2; overflow: auto; }
.CodeMirror-widget { }
.CodeMirror-wrap .CodeMirror-scroll { overflow-x: hidden; }
.CodeMirror-measure { position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden; }
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor { position: absolute; visibility: hidden; border-right: none; width: 0px; }
.CodeMirror div.CodeMirror-cursor { visibility: hidden; }
.CodeMirror-focused div.CodeMirror-cursor { visibility: inherit; }
.CodeMirror-selected { background: rgb(217, 217, 217); }
.CodeMirror-focused .CodeMirror-selected { background: rgb(215, 212, 240); }
.cm-searching { background: rgba(255, 255, 0, 0.4); }
.CodeMirror span { }
@media print { 
  .CodeMirror div.CodeMirror-cursor { visibility: hidden; }
}
.CodeMirror-lint-markers { width: 16px; }
.CodeMirror-lint-tooltip { background-color: infobackground; border: 1px solid black; border-radius: 4px; color: infotext; font-family: monospace; overflow: hidden; padding: 2px 5px; position: fixed; white-space: pre-wrap; z-index: 10000; max-width: 600px; opacity: 0; transition: opacity 0.4s; font-size: 0.8em; }
.CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning { background-position: left bottom; background-repeat: repeat-x; }
.CodeMirror-lint-mark-error { background-image: url(""); }
.CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning { background-position: center center; background-repeat: no-repeat; cursor: pointer; display: inline-block; height: 16px; width: 16px; vertical-align: middle; position: relative; }
.CodeMirror-lint-message-error, .CodeMirror-lint-message-warning { padding-left: 18px; background-position: left top; background-repeat: no-repeat; }
.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error { background-image: url(""); }
.CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning { background-image: url(""); }
.CodeMirror-lint-marker-multiple { background-image: url(""); background-repeat: no-repeat; background-position: right bottom; width: 100%; height: 100%; }


html { font-size: 14px; background-color: rgb(255, 255, 255); color: rgb(51, 51, 51); }
body { margin: 0px; padding: 0px; height: auto; bottom: 0px; top: 0px; left: 0px; right: 0px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1rem; line-height: 1.42857; overflow-x: hidden; background: inherit; }
a:active, a:hover { outline: 0px; }
.in-text-selection, ::selection { background: rgb(181, 214, 252); text-shadow: none; }
#write { margin: 0px auto; height: auto; width: inherit; word-break: normal; word-wrap: break-word; position: relative; padding-bottom: 70px; white-space: pre-wrap; overflow-x: auto; }
.for-image #write { padding-left: 8px; padding-right: 8px; }
body.typora-export { padding-left: 30px; padding-right: 30px; }
@media screen and (max-width: 500px) { 
  body.typora-export { padding-left: 0px; padding-right: 0px; }
  .CodeMirror-sizer { margin-left: 0px !important; }
  .CodeMirror-gutters { display: none !important; }
}
.typora-export #write { margin: 0px auto; }
#write > p:first-child, #write > ul:first-child, #write > ol:first-child, #write > pre:first-child, #write > blockquote:first-child, #write > div:first-child, #write > table:first-child { margin-top: 30px; }
#write li > table:first-child { margin-top: -20px; }
img { max-width: 100%; vertical-align: middle; }
input, button, select, textarea { color: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; font-size: inherit; line-height: inherit; font-family: inherit; }
input[type="checkbox"], input[type="radio"] { line-height: normal; padding: 0px; }
::before, ::after, * { box-sizing: border-box; }
#write p, #write h1, #write h2, #write h3, #write h4, #write h5, #write h6, #write div, #write pre { width: inherit; }
#write p, #write h1, #write h2, #write h3, #write h4, #write h5, #write h6 { position: relative; }
h1 { font-size: 2rem; }
h2 { font-size: 1.8rem; }
h3 { font-size: 1.6rem; }
h4 { font-size: 1.4rem; }
h5 { font-size: 1.2rem; }
h6 { font-size: 1rem; }
p { -webkit-margin-before: 1rem; -webkit-margin-after: 1rem; -webkit-margin-start: 0px; -webkit-margin-end: 0px; }
.mathjax-block { margin-top: 0px; margin-bottom: 0px; -webkit-margin-before: 0rem; -webkit-margin-after: 0rem; }
.hidden { display: none; }
.md-blockmeta { color: rgb(204, 204, 204); font-weight: bold; font-style: italic; }
a { cursor: pointer; }
#write input[type="checkbox"] { cursor: pointer; width: inherit; height: inherit; margin: 4px 0px 0px; }
tr { break-inside: avoid; break-after: auto; }
thead { display: table-header-group; }
table { border-collapse: collapse; border-spacing: 0px; width: 100%; overflow: auto; break-inside: auto; text-align: left; }
table.md-table td { min-width: 80px; }
.CodeMirror-gutters { border-right: 0px; background-color: inherit; }
.CodeMirror { text-align: left; }
.CodeMirror-placeholder { opacity: 0.3; }
.CodeMirror pre { padding: 0px 4px; }
.CodeMirror-lines { padding: 0px; }
div.hr:focus { cursor: none; }
pre { white-space: pre-wrap; }
.CodeMirror-gutters { margin-right: 4px; }
.md-fences { font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; overflow: visible; white-space: pre; background: inherit; position: relative !important; }
.md-diagram-panel { width: 100%; margin-top: 10px; text-align: center; padding-top: 0px; padding-bottom: 8px; overflow-x: auto; }
.md-fences .CodeMirror.CodeMirror-wrap { top: -1.6em; margin-bottom: -1.6em; }
.md-fences.mock-cm { white-space: pre-wrap; }
.show-fences-line-number .md-fences { padding-left: 0px; }
.show-fences-line-number .md-fences.mock-cm { padding-left: 40px; }
.footnotes { opacity: 0.8; font-size: 0.9rem; padding-top: 1em; padding-bottom: 1em; }
.footnotes + .footnotes { margin-top: -1em; }
.md-reset { margin: 0px; padding: 0px; border: 0px; outline: 0px; vertical-align: top; background: transparent; text-decoration: none; text-shadow: none; float: none; position: static; width: auto; height: auto; white-space: nowrap; cursor: inherit; -webkit-tap-highlight-color: transparent; line-height: normal; font-weight: normal; text-align: left; box-sizing: content-box; direction: ltr; }
li div { padding-top: 0px; }
blockquote { margin: 1rem 0px; }
li p, li .mathjax-block { margin: 0.5rem 0px; }
li { margin: 0px; position: relative; }
blockquote > :last-child { margin-bottom: 0px; }
blockquote > :first-child { margin-top: 0px; }
.footnotes-area { color: rgb(136, 136, 136); margin-top: 0.714rem; padding-bottom: 0.143rem; }
@media print { 
  html, body { height: 100%; }
  .typora-export * { -webkit-print-color-adjust: exact; }
  h1, h2, h3, h4, h5, h6 { break-after: avoid-page; orphans: 2; }
  p { orphans: 4; }
  html.blink-to-pdf { font-size: 13px; }
  .typora-export #write { padding-left: 1cm; padding-right: 1cm; }
  .typora-export #write::after { height: 0px; }
  @page { margin: 20mm 0mm; }
}
.footnote-line { margin-top: 0.714em; font-size: 0.7em; }
a img, img a { cursor: pointer; }
pre.md-meta-block { font-size: 0.8rem; min-height: 2.86rem; white-space: pre-wrap; background: rgb(204, 204, 204); display: block; overflow-x: hidden; }
p .md-image:only-child { display: inline-block; width: 100%; text-align: center; }
#write .MathJax_Display { margin: 0.8em 0px 0px; }
.mathjax-block { white-space: pre; overflow: hidden; width: 100%; }
p + .mathjax-block { margin-top: -1.143rem; }
.mathjax-block:not(:empty)::after { display: none; }
[contenteditable="true"]:active, [contenteditable="true"]:focus { outline: none; box-shadow: none; }
.task-list { list-style-type: none; }
.task-list-item { position: relative; padding-left: 1em; }
.task-list-item input { position: absolute; top: 0px; left: 0px; }
.math { font-size: 1rem; }
.md-toc { min-height: 3.58rem; position: relative; font-size: 0.9rem; border-radius: 10px; }
.md-toc-content { position: relative; margin-left: 0px; }
.md-toc::after, .md-toc-content::after { display: none; }
.md-toc-item { display: block; color: rgb(65, 131, 196); text-decoration: none; }
.md-toc-inner:hover { }
.md-toc-inner { display: inline-block; cursor: pointer; }
.md-toc-h1 .md-toc-inner { margin-left: 0px; font-weight: bold; }
.md-toc-h2 .md-toc-inner { margin-left: 2em; }
.md-toc-h3 .md-toc-inner { margin-left: 4em; }
.md-toc-h4 .md-toc-inner { margin-left: 6em; }
.md-toc-h5 .md-toc-inner { margin-left: 8em; }
.md-toc-h6 .md-toc-inner { margin-left: 10em; }
@media screen and (max-width: 48em) { 
  .md-toc-h3 .md-toc-inner { margin-left: 3.5em; }
  .md-toc-h4 .md-toc-inner { margin-left: 5em; }
  .md-toc-h5 .md-toc-inner { margin-left: 6.5em; }
  .md-toc-h6 .md-toc-inner { margin-left: 8em; }
}
a.md-toc-inner { font-size: inherit; font-style: inherit; font-weight: inherit; line-height: inherit; }
.footnote-line a:not(.reversefootnote) { color: inherit; }
.md-attr { display: none; }
.md-fn-count::after { content: "."; }
.md-tag { opacity: 0.5; }
.md-comment { color: rgb(162, 127, 3); opacity: 0.8; font-family: monospace; }
code { text-align: left; }
h1 .md-tag, h2 .md-tag, h3 .md-tag, h4 .md-tag, h5 .md-tag, h6 .md-tag { font-weight: initial; opacity: 0.35; }
a.md-print-anchor { border-width: initial !important; border-style: none !important; border-color: initial !important; display: inline-block !important; position: absolute !important; width: 1px !important; right: 0px !important; outline: none !important; background: transparent !important; text-decoration: initial !important; text-shadow: initial !important; }
.md-inline-math .MathJax_SVG .noError { display: none !important; }
.mathjax-block .MathJax_SVG_Display { text-align: center; margin: 1em 0em; position: relative; text-indent: 0px; max-width: none; max-height: none; min-height: 0px; min-width: 100%; width: auto; display: block !important; }
.MathJax_SVG_Display, .md-inline-math .MathJax_SVG_Display { width: auto; margin: inherit; display: inline-block !important; }
.MathJax_SVG .MJX-monospace { font-family: monospace; }
.MathJax_SVG .MJX-sans-serif { font-family: sans-serif; }
.MathJax_SVG { display: inline; font-style: normal; font-weight: normal; line-height: normal; zoom: 90%; text-indent: 0px; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border: 0px; padding: 0px; margin: 0px; }
.MathJax_SVG * { transition: none; }


@font-face { font-family: "PT Serif"; font-style: normal; font-weight: normal; src: local("PT Serif"), local("PTSerif-Regular"), url("./newsprint/PT_Serif-Web-Regular.ttf"); }
@font-face { font-family: "PT Serif"; font-style: italic; font-weight: normal; src: local("PT Serif"), local("PTSerif-Italic"), url("./newsprint/PT_Serif-Web-Italic.ttf"); }
@font-face { font-family: "PT Serif"; font-style: normal; font-weight: bold; src: local("PT Serif"), local("PTSerif-Bold"), url("./newsprint/PT_Serif-Web-Bold.ttf"); }
@font-face { font-family: "PT Serif"; font-style: italic; font-weight: bold; src: local("PT Serif"), local("PTSerif-BoldItalic"), url("./newsprint/PT_Serif-Web-BoldItalic.ttf"); }
html { font-size: 16px; }
html, body { background-color: rgb(243, 242, 238); font-family: "PT Serif", "Times New Roman", Times; color: rgb(31, 9, 9); line-height: 1.5em; }
#write { max-width: 40em; }
ol, ul { list-style: none; }
blockquote, q { quotes: none; }
blockquote::before, blockquote::after, q::before, q::after { content: none; }
table { border-collapse: collapse; border-spacing: 0px; }
h1, h2, h3, h4, h5, h6 { font-weight: bold; }
h1 { font-size: 1.875em; line-height: 1.6em; margin-top: 2em; }
h2, h3 { font-size: 1.3125em; line-height: 1.15; margin-top: 2.28571em; margin-bottom: 1.15em; }
h3 { font-weight: normal; }
h4 { font-size: 1.125em; margin-top: 2.67em; }
h5, h6 { font-size: 1em; }
h1 { border-bottom: 1px solid; margin-bottom: 1.875em; padding-bottom: 0.8125em; }
a { text-decoration: none; color: rgb(6, 85, 136); }
a:hover, a:active { text-decoration: underline; }
p, blockquote, .md-fences { margin-bottom: 1.5em; }
h1, h2, h3, h4, h5, h6 { margin-bottom: 1.5em; }
blockquote { font-style: italic; border-left: 5px solid; margin-left: 2em; padding-left: 1em; }
ul, ol { margin: 0px 0px 1.5em 1.5em; }
ol li { list-style-type: decimal; list-style-position: outside; }
ul li { list-style-type: disc; list-style-position: outside; }
.md-meta, .md-before, .md-after { color: rgb(153, 153, 153); }
table { margin-bottom: 1.5em; font-size: 1em; }
thead th, tfoot th { padding: 0.25em 0.25em 0.25em 0.4em; text-transform: uppercase; }
th { text-align: left; }
td { vertical-align: top; padding: 0.25em 0.25em 0.25em 0.4em; }
code, .md-fences { background-color: rgb(218, 218, 218); padding-left: 1ch; padding-right: 1ch; }
.md-fences { margin-left: 2em; margin-bottom: 3em; }
.md-fences .CodeMirror.CodeMirror-wrap { top: -0.8em; }
pre, code, tt { font-size: 0.875em; line-height: 1.71428em; }
h1 { line-height: 1.3em; font-weight: normal; margin-bottom: 0.5em; }
p + ul, p + ol { margin-top: -1em; }
h3 + ul, h4 + ul, h5 + ul, h6 + ul, h3 + ol, h4 + ol, h5 + ol, h6 + ol { margin-top: 0.5em; }
li > ul, li > ol { margin-top: inherit; }
h2, h3 { margin-bottom: 0.75em; }
hr { border-top: none; border-right: none; border-bottom: 1px solid; border-left: none; }
h1 { border-color: rgb(197, 197, 197); }
blockquote { border-color: rgb(186, 186, 186); color: rgb(101, 101, 101); }
thead.md-table-edit { background-color: transparent; }
thead { background-color: rgb(218, 218, 218); }
tr:nth-child(2n) { background: rgb(232, 231, 231); }
hr { border-color: rgb(197, 197, 197); }
.task-list { padding-left: 1rem; }
.task-list-item { padding-left: 1.5rem; list-style-type: none; }
.task-list-item input::before { content: "√"; display: inline-block; width: 1.25rem; height: 1.6rem; vertical-align: middle; text-align: center; color: rgb(221, 221, 221); background-color: rgb(243, 242, 238); }
.task-list-item input:checked::before, .task-list-item input[checked]::before { color: inherit; }
#write pre.md-meta-block { min-height: 1.875rem; color: rgb(85, 85, 85); border: 0px; background: transparent; margin-left: 1em; margin-top: 1em; }
.md-image > .md-meta { color: rgb(155, 81, 70); }
.md-expand.md-image > .md-meta { background-color: rgba(255, 255, 255, 0.65098); }
.md-image > .md-meta { font-family: Menlo, "Ubuntu Mono", Consolas, "Courier New", "Microsoft Yahei", "Hiragino Sans GB", "WenQuanYi Micro Hei", sans-serif; }
#write > h3.md-focus::before { left: -1.5rem; color: rgb(153, 153, 153); border-color: rgb(153, 153, 153); }
#write > h4.md-focus::before { left: -1.5rem; top: 0.25rem; color: rgb(153, 153, 153); border-color: rgb(153, 153, 153); }
#write > h5.md-focus::before { left: -1.5rem; color: rgb(153, 153, 153); border-color: rgb(153, 153, 153); }
#write > h6.md-focus::before { left: -1.5rem; top: 0.3125rem; color: rgb(153, 153, 153); border-color: rgb(153, 153, 153); }
.md-toc:focus .md-toc-content { margin-top: 19px; }
.md-toc-content:empty::before { color: rgb(6, 85, 136); }
.md-toc-item { color: rgb(6, 85, 136); }
#write div.md-toc-tooltip { background-color: rgb(243, 242, 238); }
#outline-dropmenu { background-color: rgb(243, 242, 238); box-shadow: rgba(0, 0, 0, 0.372549) 0px 6px 12px; }
.pin-outline #outline-dropmenu { background: inherit; box-shadow: none; border-right: 1px dashed; }
.pin-outline #outline-dropmenu:hover .outline-title-wrapper { border-left: 1px dashed; }
.outline-item:hover { background-color: rgb(218, 218, 218); border-left: 28px solid rgb(218, 218, 218); border-right: 18px solid rgb(218, 218, 218); }
.typora-node .outline-item:hover { border-right: 28px solid rgb(218, 218, 218); }
.outline-expander::before { content: ""; font-family: FontAwesome; font-size: 14px; top: 1px; }
.outline-expander:hover::before, .outline-item-open > .outline-item > .outline-expander::before { content: ""; }
.modal-content { background-color: rgb(243, 242, 238); }
.auto-suggest-container ul li { list-style-type: none; }
.megamenu-menu, #top-titlebar, #top-titlebar *, .megamenu-content { background: rgb(243, 242, 238); color: rgb(31, 9, 9); }
.megamenu-menu-header { border-bottom: 1px dashed rgb(32, 43, 51); }
.megamenu-menu { box-shadow: none; border-right: 1px dashed; }
header, .context-menu, .megamenu-content, footer { font-family: "PT Serif", "Times New Roman", Times; color: rgb(31, 9, 9); }
#megamenu-back-btn { color: rgb(31, 9, 9); border-color: rgb(31, 9, 9); }
.megamenu-menu-header #megamenu-menu-header-title::before { color: rgb(31, 9, 9); }
.megamenu-menu-list li a:hover, .megamenu-menu-list li a.active { color: inherit; background-color: rgb(232, 231, 223); }
.long-btn:hover { background-color: rgb(232, 231, 223); }
#recent-file-panel tbody tr:nth-child(2n-1) { background-color: transparent !important; }
.megamenu-menu-panel tbody tr:hover td:nth-child(2) { color: inherit; }
.megamenu-menu-panel .btn { background-color: rgb(210, 209, 209); }
.btn-default { background-color: transparent; }
.typora-sourceview-on #toggle-sourceview-btn, .show-word-count #footer-word-count { background: rgb(199, 197, 197); }
#typora-quick-open { background-color: inherit; }
.md-diagram-panel { margin-left: -1ch; margin-top: 24px; }






</style>
</head>
<body class='typora-export' >
<div  id='write'  class = 'is-node'><h1><a name='header-c1' class='md-header-anchor '></a>Angular学习（了解）</h1><h3><a name='header-c6' class='md-header-anchor '></a>一、概念</h3><p>​	一套用户构建用户界面的js框架，由goole开发和维护，主要被用来开发单页面（SPA）应用程序</p><h3><a name='header-c9' class='md-header-anchor '></a>二、特性</h3><ul><li>MVVM</li><li>组件化</li><li>模块化</li><li>指令</li><li>服务</li><li>依赖注入</li><li>TypeScript</li><li>...</li></ul><p>学习建议：</p><ul><li>读官方文档</li><li>写 demo 测试</li><li>写小项目练手</li><li>参与实际项目开发经验</li><li>日积月累....</li></ul><p><strong>相关链接：</strong></p><ul><li><a href='https://zh.wikipedia.org/wiki/Angular'>维基百科 - Angular</a></li><li><a href='https://angularjs.org/'>AngularJS 1.x.x 官网</a></li><li><a href='https://angular.io/'>Angular 官网</a></li><li><a href='https://github.com/angular/angular'>Angular Github</a></li><li><a href='https://angular.io/docs'>Angular 官方文档</a></li><li><a href='https://angular.io/tutorial'>Angular 官方教程</a></li><li><a href='https://angular.io/api'>Angular APi文档</a></li></ul><h2><a name='header-c77' class='md-header-anchor '></a>Angular-cli脚手架安装</h2><p>​	目前，无论你使用什么前端框架，都必然要使用到各种 NodeJS 工具，Angular 也不例外。与其它框架不同，Angular 从一开始就走的“全家桶”式的设计思路，因此 @angular/cli 这款工具里面集成了日常开发需要使用的所有 Node 模块，使用 @angular/cli 可以大幅度降低搭建开发环境的难度。</p><p>Angular CLI 类似于 Vue CLI，是 Angular 官方开发的一个脚手架工具，专门用来开发构建 Angular 应用程序。</p><ul><li>Angular 应用程序初始化</li><li>内置开发服务器</li><li>代码变更浏览器自动刷新</li><li>创建组件、指令、服务等集成工具</li><li>测试和维护</li><li>......</li></ul><h2><a name='header-c101' class='md-header-anchor '></a>Angular-cli安装步骤</h2><h3><a name='header-c102' class='md-header-anchor '></a>1、安装 Node.js</h3><ul><li>下载地址：<a href='https://nodejs.org/en/download/' target='_blank' >https://nodejs.org/en/download/</a></li></ul><h3><a name='header-c107' class='md-header-anchor '></a>2、安装 npm</h3><ul><li>npm 会随着 Node 的安装被一起安装</li></ul><h3><a name='header-c112' class='md-header-anchor '></a>3、安装 Python</h3><ul><li>下载地址：<a href='https://www.python.org/downloads/release/python-2714/' target='_blank' >https://www.python.org/downloads/release/python-2714/</a></li><li>Windows 32 位：<a href='https://www.python.org/ftp/python/2.7.14/python-2.7.14.msi' target='_blank' >https://www.python.org/ftp/python/2.7.14/python-2.7.14.msi</a></li><li>Windows 64位：<a href='https://www.python.org/ftp/python/2.7.14/python-2.7.14.amd64.msi' target='_blank' >https://www.python.org/ftp/python/2.7.14/python-2.7.14.amd64.msi</a></li><li>确认 Python 环境</li></ul><p>确认是否安装成功：python --version</p><h3><a name='header-c128' class='md-header-anchor '></a>4、安装 C++ 编译工具</h3><ul><li><p><code>Angular CLi</code> 在 Windows 上同时依赖 C++ 编译工具，所以我们这里也需要单独安装。</p></li><li><p>当然如果你的机器安装了安装了Visual Studio就不用安装了（因为自带了）</p></li><li><p>执行下面的命名安装 C++ 编译工具：</p><p>npm install --global --production windows-build-tools</p></li></ul><h2><a name='header-c141' class='md-header-anchor '></a>使用脚手架工具初始化项目</h2><ul><li>选择要创建项目的路径，然后执行：ng new my-app；（其中my-app表示要创建项目名）</li><li>执行完毕会生成my-app文件夹</li></ul><p>注意事项：</p><ol start='' ><li>安装过程中会失败或者一直卡住</li><li>所以这个时候果断打断下载：cd  到  my-app路径下，执行：cnpm i（推荐使用: yarn install）</li><li>安装yarn方法： npm i yarn -v；和nrm作用一样，下载更快</li></ol><h2><a name='header-c161' class='md-header-anchor '></a>启动Angular开发模式23</h2><ul><li>或者 npm start</li><li>ng serve</li></ul><p><strong>注意：</strong></p><ol start='' ><li>在项目根目录下执行</li><li>看好是 <code>serve</code> 不是 server</li><li>该命令默认会开启一个服务占用 4200 端口，如果想要修改可以通过 <code>--port</code> 参数来指定，例如 <code>ng serve --port 3000</code></li></ol><h2><a name='header-c181' class='md-header-anchor '></a>一些常见的坑</h2><p>@angular/cli 这种“全家桶”式的设计带来了很大的方便，同时也有一些人不太喜欢，因为很多底层的东西被屏蔽掉了，开发者不能天马行空地自由发挥。比如：@angular/cli 把底层 webpack 的配置文件屏蔽掉了，很多喜欢自己手动配 webpack 的开发者就感到很不爽。</p><p>对于国内的开发者来说，上面这些其实不是最重要的，国内开发者碰到的坑主要是由两点引起的：</p><ol start='' ><li>第一点是网络问题：比如 <code>node-sass</code> 这个模块你很有可能就装不上，原因你懂的。</li><li>第二点是开发环境导致的问题：国内使用 Windows 平台的开发者比例依然巨大，而 @angular/cli 在 Windows 平台上有一些非常恶心的依赖，比如它需要依赖 python 环境、Visual Studio 环境。</li></ol><p>所以，如果你的开发平台是 Windows，请特别注意：</p><ol start='' ><li>如果你知道如何给 npm 配置代理，也知道如何翻墙，请首选 npm 来安装 @angular/cli。</li><li>否则，请使用 cnpm 来安装 @angular/cli，原因有三：1、cnpm 的缓存服务器在国内，你装东西的速度会快很多；2、用 cnpm 可以帮你避开某些模块装不上的问题，因为它在服务器上面做了缓存；3、cnpm 还把一些包都预编译好了缓存在服务端，不需要把源码下载到你本地去编译，所以你的机器上可以没有那一大堆麻烦的环境。</li><li>如果安装失败，请手动把 node_modules 目录删掉重试一遍，全局的 @angular/cli 也需要删掉重装，cnpm uninstall -g @angular/cli。</li><li>如果 node_modules 删不掉，爆出路径过长之类的错误，请尝试用一些文件粉碎机之类的工具强行删除。</li><li>无论你用什么开发环境，安装的过程中请仔细看 log。很多朋友没有看 log 的习惯，报错的时候直接懵掉，根本不知道发生了什么。</li></ol><h2><a name='header-c211' class='md-header-anchor '></a>关于编辑器的选择</h2><p>如你所知，一直以来，前端开发领域并没有一款特别好用的开发和调试工具。</p><ul><li>WebStorm 很强大，但是吃资源很严重。</li><li>Sublime Text 插件很多，可惜要收费，而国内的企业还没有养成花钱购买开发工具的习惯。</li><li>Chrome 的开发者工具很好用，但是要直接调试 TypeScript 很麻烦。</li></ul><p>所以，Visual Studio Code（简称 VS Code）才会呈现出爆炸性增长的趋势。它是微软开发的一款编辑器，完全<a href='https://github.com/Microsoft/vscode'>开源免费</a>。VS Code 底层是 Electron，界面本身是用 TypeScript 开发的。对于 Angular 开发者来说，当然要强烈推荐 VS Code。最值得一提的是，从1.14开始，可以直接在 VS Code 里面调试 TypeScript 代码。</p><p>项目结构介绍</p><h1><a name='header-c228' class='md-header-anchor '></a>正式进入Angluar学习</h1><h2><a name='header-c229' class='md-header-anchor '></a>Angular项目启动过程</h2><p><img src='./md%E6%96%87%E6%A1%A3%E5%9B%BE%E7%89%87/ng%E5%90%AF%E5%8A%A8%E8%BF%87%E7%A8%8B.png' alt='ng启动过程.png' /></p><h2><a name='header-c232' class='md-header-anchor '></a>项目结构介绍</h2><p>├── e2e    端到端测试（暂且不关心）
├── node_modules npm   安装的第三方包
├── src    存放业务源码
├── .angular.json      AngularCLI脚手架工具配置文件
├── .editorconfig    针对编辑器的代码风格约束
├── .gitignore Git   仓库忽略配置项
├── karma.conf.js    测试配置文件（给karma用的，暂且不用关心）
├── package.json    项目包说明文件
├── protractor.conf.js    端到端测试配置文件（暂且不用关心）
├── README.md    项目说明文件
├── tsconfig.json TypeScript   配置文件
└── tslint.json TypeScript   代码风格校验工具配置文件（类似于 eslint）</p><h2><a name='header-c246' class='md-header-anchor '></a>angular常用指令</h2><p>&quot;scripts&quot;: {</p><pre class='md-fences mock-cm' style='display:block;position:relative'>&quot;ng&quot;: &quot;ng&quot;, 运行查看 Angular CLI 脚手架工具使用帮助
&quot;start&quot;: &quot;ng serve&quot;, 运行开发模式
&quot;build&quot;: &quot;ng build --prod&quot;, 运行项目打包构建（用于发布到生成环境）
&quot;test&quot;: &quot;ng test&quot;, 运行karma单元测试
&quot;lint&quot;: &quot;ng lint&quot;, 运行TypeScript代码校验
&quot;e2e&quot;: &quot;ng e2e&quot; 运行protractor端到端测试</pre><p>  },</p><h2><a name='header-c252' class='md-header-anchor '></a>angular.json文件内容介绍</h2><p>{
  &quot;$schema&quot;: &quot;./node_modules/@angular/cli/lib/config/schema.json&quot;,
  &quot;project&quot;: {</p><pre class='md-fences mock-cm' style='display:block;position:relative'>&quot;name&quot;: &quot;my-app&quot;</pre><p>  },
  &quot;apps&quot;: [</p><pre class='md-fences mock-cm' style='display:block;position:relative'>{
  &quot;root&quot;: &quot;src&quot;, 源码根目录
  &quot;outDir&quot;: &quot;dist&quot;, 打包编译结果目录
  &quot;assets&quot;: [ 存放静态资源目录
    &quot;assets&quot;,
    &quot;favicon.ico&quot;
  ],
  &quot;index&quot;: &quot;index.html&quot;, 单页面
  &quot;main&quot;: &quot;main.ts&quot;, 模块启动入口
  &quot;polyfills&quot;: &quot;polyfills.ts&quot;, 用以兼容低版本浏览器不支持的 JavaScript 语法特性
  &quot;test&quot;: &quot;test.ts&quot;, 测试脚本
  &quot;tsconfig&quot;: &quot;tsconfig.app.json&quot;,
  &quot;testTsconfig&quot;: &quot;tsconfig.spec.json&quot;,
  &quot;prefix&quot;: &quot;app&quot;, 使用脚手架工具创建组件的自动命名前缀
  &quot;styles&quot;: [ 全局样式文件
    &quot;styles.css&quot;
  ],
  &quot;scripts&quot;: [], 全局脚本文件
  &quot;environmentSource&quot;: &quot;environments/environment.ts&quot;,
  &quot;environments&quot;: {
    &quot;dev&quot;: &quot;environments/environment.ts&quot;,
    &quot;prod&quot;: &quot;environments/environment.prod.ts&quot;
  }
}</pre><p>  ],
  &quot;e2e&quot;: { 端到端测试相关配置</p><pre class='md-fences mock-cm' style='display:block;position:relative'>&quot;protractor&quot;: {
  &quot;config&quot;: &quot;./protractor.conf.js&quot;
}</pre><p>  },
  &quot;lint&quot;: [ TypeScript代码风格校验相关配置</p><pre class='md-fences mock-cm' style='display:block;position:relative'>{
  &quot;project&quot;: &quot;src/tsconfig.app.json&quot;,
  &quot;exclude&quot;: &quot;**/node_modules/**&quot;
},
{
  &quot;project&quot;: &quot;src/tsconfig.spec.json&quot;,
  &quot;exclude&quot;: &quot;**/node_modules/**&quot;
},
{
  &quot;project&quot;: &quot;e2e/tsconfig.e2e.json&quot;,
  &quot;exclude&quot;: &quot;**/node_modules/**&quot;
}</pre><p>  ],
  &quot;test&quot;: { karma单元测试相关配置</p><pre class='md-fences mock-cm' style='display:block;position:relative'>&quot;karma&quot;: {
  &quot;config&quot;: &quot;./karma.conf.js&quot;
}</pre><p>  },
  &quot;defaults&quot;: { 默认后缀名</p><pre class='md-fences mock-cm' style='display:block;position:relative'>&quot;styleExt&quot;: &quot;css&quot;,
&quot;component&quot;: {}</pre><p>  }
}</p><h1><a name='header-c281' class='md-header-anchor '></a>Angular “概念模型”</h1><h2><a name='header-c282' class='md-header-anchor '></a>Angular 组件component</h2><ul><li>几乎所有前端框架都在玩“组件化”，而且最近都不约而同地选择了“标签化”这种思路，Angular 也不例外。</li><li>对新版本的 Angular 来说，一切都是围绕着“组件化”展开的，组件是 Angular 的核心概念模型。</li></ul><h2><a name='header-c290' class='md-header-anchor '></a>组件化的意义</h2><ol start='' ><li>第一是分治，因为有了组件之后，我们可以把各种逻辑封装在组件内部，避免混在一起</li><li>第二是复用，封装成组件之后不仅可以在项目内部复用，而且可以沉淀下来跨项目复用</li></ol><h2><a name='header-c298' class='md-header-anchor '></a>组件的定义</h2><p>以下是一个最简单的 Angular 组件定义（一般自动生成）：</p><pre class="md-fences md-end-block" lang="javascript"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment">// 加载器其他组件</span></span></pre></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">import</span> { <span class="cm-def">Component</span> } <span class="cm-keyword">from</span> <span class="cm-string">'@angular/core'</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">@<span class="cm-variable">Component</span>({</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">selector</span>: <span class="cm-string">'app-root'</span>,</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">templateUrl</span>: <span class="cm-string">'./app.component.html'</span>,</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">styleUrls</span>: [<span class="cm-string">'./app.component.css'</span>]</span></pre><pre class=""><span style="padding-right: 0.1px;">})</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">export</span> <span class="cm-keyword">class</span> <span class="cm-def">AppComponent</span> {</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">title</span> <span class="cm-operator">=</span> <span class="cm-string">'熊刚先生'</span>; <span class="cm-comment">//自定义数据</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-variable">txt</span> <span class="cm-operator">=</span> <span class="cm-string">'用一往无前的勇气打败所有的焦虑'</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-variable">count</span><span class="cm-operator">=</span><span class="cm-number">0</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-variable">increment</span> <span class="cm-operator">=</span> <span class="cm-keyword">function</span>(){ <span class="cm-comment">//创建方法，可以通过事件访问</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-keyword">this</span>.<span class="cm-property">count</span><span class="cm-operator">++</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  }</span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 360px;"></div></div></div></pre><ul><li><code>@Component</code>：这是一个 Decorator（装饰器），其作用类似于 Java 里面的注解。Decorator 这个语言特性目前（2017-10）处于 Stage 2（草稿）状态，还不是 ECMA 的正式规范。</li><li><code>selector</code>：组件的标签名，外部使用者可以这样来使用这个组件：<app-root>。默认情况下，ng 命令生成出来的组件都会带上一个 app 前缀，如果你不喜欢，可以在 angular-cli.json 里面修改 prefix 配置项，设置为空字符串将会不带任何前缀。</li><li><code>templateUrl</code>：引用外部的 HTML 模板。如果你想直接编写内联模板，可以使用 template，支持 ES6 引入的<a href='http://es6.ruanyifeng.com/#docs/string'>“模板字符串”写法</a>。</li><li><code>styleUrls</code>：引用外部 CSS 样式文件，这是一个数组，也就意味着可以引用多份 CSS 文件。</li><li><code>export class AppComponent</code>：这是 ES6 里面引入的模块和 class 定义方式。</li></ul><h3><a name='header-c318' class='md-header-anchor '></a>组件中的点击事件</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>&lt;button type=&quot;button&quot; class=&quot;btn btn-default&quot; (click)=&quot;increment()&quot;&gt;点击按钮&lt;/button&gt;</pre><h2><a name='header-c320' class='md-header-anchor '></a>创建组件</h2><ul><li>执行：ng generate component foo;   (foo表示组件名)</li><li>会自动更新：app.moudule.ts文件</li><li>在app.component.html中引用新组件：
组件标签名以foocomponent.ts中：selector: &#39;app-foo&#39;为准<strong><app-foo></app-foo></strong></li></ul><h2><a name='header-c332' class='md-header-anchor '></a>元数据（Metadata）</h2><p>元数据告诉 Angular 如何处理组件类。</p><pre class="md-fences md-end-block" lang="typescript"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;">@<span class="cm-variable">Component</span>({</span></pre></div><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">selector</span>: <span class="cm-string">'app-root'</span>,</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">templateUrl</span>: <span class="cm-string">'./app.component.html'</span>,</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">styleUrls</span>: [<span class="cm-string">'./app.component.css'</span>]</span></pre><pre class=""><span style="padding-right: 0.1px;">})</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">export</span> <span class="cm-keyword">class</span> <span class="cm-def">AppComponent</span> {</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">title</span> <span class="cm-operator">=</span> <span class="cm-string">'你的第一个 Angular 应用'</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 192px;"></div></div></div></pre><h2><a name='header-c336' class='md-header-anchor '></a>数据绑定（Data binding）</h2><p>和 Vue.js 一样，MVVM 思想（数据驱动视图），通过特殊的 <code>{{}}</code> 语法将数据绑定到 DOM 元素，当数据改变的时候会影响视图的更新。</p><pre class="md-fences md-end-block" lang="html"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment">&lt;!--The content below is only a placeholder and can be replaced.--&gt;</span></span></pre></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-tag cm-bracket">&lt;</span><span class="cm-tag">div</span> <span class="cm-attribute">style</span>=<span class="cm-string">"text-align:center"</span><span class="cm-tag cm-bracket">&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-tag cm-bracket">&lt;</span><span class="cm-tag">h1</span><span class="cm-tag cm-bracket">&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  Welcome to {{ title }}!</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-tag cm-bracket">&lt;/</span><span class="cm-tag">h1</span><span class="cm-tag cm-bracket">&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-tag cm-bracket">&lt;/</span><span class="cm-tag">div</span><span class="cm-tag cm-bracket">&gt;</span></span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 144px;"></div></div></div></pre><h2><a name='header-c340' class='md-header-anchor '></a>指令（Directives）</h2><p>和 Vue.js 一样，Angular 扩展了 HTML 语法，增加了一些特殊的属性指令，例如：</p><ul><li><code>*ngFor</code> 循环指令:<tr *ngFor="let item of contacts;let i = index"> <td>{{item.name}}</td></tr></li><li><code>*ngIf</code> 条件判断指令:<div *ngIf="email.errors.required">邮箱不能为空！</div></li><li><code>[(ngModel)]</code> 表单控件双向绑定指令:[(ngModel)] = &quot;siginupFrom.email&quot;</li></ul><h2><a name='header-c353' class='md-header-anchor '></a>Services（服务）</h2><ul><li>服务是一个广义范畴，包括：值、函数，或应用所需的功能。</li><li>说白了服务就是针对某个单一或系统功能的封装</li><li>典型：一个服务就是 Http 服务</li></ul><h2><a name='header-c364' class='md-header-anchor '></a>依赖注入（Dependency injection）</h2><ul><li>“依赖注入”是提供类的新实例的一种方式</li><li>还负责处理好类所需的全部依赖。</li><li>大多数依赖都是服务。 </li><li>Angular 使用依赖注入来提供新组件以及组件所需的服务。</li></ul><h2><a name='header-c378' class='md-header-anchor '></a>总结</h2><p>我们学到的这些只是关于 Angular 应用程序的八个主要构造块的基础知识：</p><ul><li><a href='https://angular.cn/guide/architecture#modules'>模块</a></li><li><a href='https://angular.cn/guide/architecture#components'>组件</a></li><li><a href='https://angular.cn/guide/architecture#templates'>模板</a></li><li><a href='https://angular.cn/guide/architecture#metadata'>元数据</a></li><li><a href='https://angular.cn/guide/architecture#data-binding'>数据绑定</a></li><li><a href='https://angular.cn/guide/architecture#directives'>指令</a></li><li><a href='https://angular.cn/guide/architecture#services'>服务</a></li><li><a href='https://angular.cn/guide/architecture#dependency-injection'>依赖注入</a></li></ul><p>这是 Angular 应用程序中所有其它东西的基础，要使用 Angular，以这些作为开端就绰绰有余了。 但它仍然没有包含我们需要知道的全部。</p><p>这里是一个简短的、按字母排序的列表，列出了其它重要的 Angular 特性和服务。</p><ul><li>动画</li><li>表单</li><li>HTTP</li><li>组件生命周期</li><li>管道过滤器</li><li>路由</li><li>测试</li></ul><h1><a name='header-c432' class='md-header-anchor '></a>TypeScript介绍</h1><p>TypeScript 是 JavaScript 的强类型版本。然后在编译期去掉类型和特有语法，生成纯粹的 JavaScript 代码。由于最终在浏览器中运行的仍然是 JavaScript，所以 TypeScript 并不依赖于浏览器的支持，也并不会带来兼容性问题。</p><p>TypeScript 是 JavaScript 的超集，这意味着他支持所有的 JavaScript 语法。并在此之上对 JavaScript 添加了一些扩展，如 class / interface / module 等。这样会大大提升代码的可阅读性。</p><p>和 JavaScript 若类型不同，TypeScript 这种强类型语言最大的优势在于静态类型检查，可以在代码开发阶段就预知一些低级错误的发生。</p><ul><li>一种类似于 JavaScript 的语言，在 JavaScript 的基础之上增加了类型，同时增强了 JavaScript 部分语法功能</li><li>遵循 EcmaScript 6 标准规范</li><li>由微软开发</li><li>Angular 2 框架采用 TypeScript 编写</li><li>背后有微软和谷歌两大公司的支持</li><li>TypeScript 可以编译成 JavaScript 从而在支持 JavaScript 的环境中运行</li><li>TypeScript 和 JavaScript 的关系就好比 less 和 css 的关系</li></ul><h2><a name='header-c461' class='md-header-anchor '></a>静态类型和动态类型</h2><ul><li>静态（static）：无需运行，根据程序代码就能确定结果。</li><li>动态（dynamic）：只有运行才能确定结果。</li><li>类型：对某个数据所具有的性质进行的描述。如它的结构是怎样的，能进行什么操作。</li><li>静态类型：数据拥有类型，且仅有数据拥有类型。</li><li>动态类型：数据拥有类型，存放数据的变量、表达式也拥有类型，且类型在编译时是固定的。</li></ul><p><img src='./md%E6%96%87%E6%A1%A3%E5%9B%BE%E7%89%87/%E5%8A%A8%E6%80%81%E5%92%8C%E9%9D%99%E6%80%81%E7%B1%BB%E5%9E%8B%E6%AF%94%E8%BE%83.jpg' alt='' /></p><p>从表中可见，动态语言和静态语言各有优劣，而TypeScript提供了静态语言强类型支持，同时兼容动态语言弱类型的语法，使用者根据项目需求自由选择。</p><h2><a name='header-c482' class='md-header-anchor '></a>相关链接</h2><ul><li><a href='https://zh.wikipedia.org/wiki/TypeScript'>维基百科 - TypeScript</a></li></ul><ul><li><a href='https://www.zhihu.com/question/21879449?sort=created'>如何评价 TypeScript？</a></li><li><a href='https://www.zhihu.com/question/28016252/answer/39056940'>flow.js/typescript 这类定义参数类型的意义何在？</a></li></ul><ul><li><a href='https://github.com/Microsoft/TypeScript'>TypeScript Github</a></li><li><a href='https://www.typescriptlang.org/'>TypeScript 官网</a></li><li><a href='https://www.tslang.cn/'>[TypeScript 中文网](https://www.tslang.cn/)</a></li></ul><h2><a name='header-c504' class='md-header-anchor '></a>搭建 TypeScript 开发环境</h2><ul><li><p>什么是 compiler？</p></li><li><p>less 编译器：<code>less</code></p></li><li><p>EcmaScript 6 编译器：<code>babel</code></p></li><li><p>TypeScript 编译器：<code>typescript</code></p></li><li><p>一句话：把 TypeScript 转换为 JavaScript ，浏览器就具有运行了</p></li><li><p>在线测试编译环境 compiler</p><ul><li><a href='https://www.typescriptlang.org/play/index.html' target='_blank' >https://www.typescriptlang.org/play/index.html</a></li></ul></li><li><p>本地开发编译环境</p><pre class='md-fences mock-cm' style='display:block;position:relative'>npm i -g typescript
# 查看版本号
tsc --version
# 查看使用帮助
tsc --help</pre></li></ul><h3><a name='header-c532' class='md-header-anchor '></a>编译成js</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>//编译成js命令
tsc greeter.ts</pre><h2><a name='header-c534' class='md-header-anchor '></a>变量声明</h2><h3><a name='header-c535' class='md-header-anchor '></a><code>var</code></h3><ul><li>作用域</li><li>重复声明</li></ul><h3><a name='header-c543' class='md-header-anchor '></a><code>let</code></h3><ul><li>块级作用域</li><li>在同一个块中不能重复声明</li></ul><h3><a name='header-c551' class='md-header-anchor '></a><code>const</code></h3><ul><li><p>声明同时必须赋值</p></li><li><p>一定声明不可改变</p><ul><li>对象可以修改</li></ul></li><li><p>块级作用域</p></li></ul><h3><a name='header-c566' class='md-header-anchor '></a><code>let</code> vs <code>const</code></h3><p>使用<a href='https://en.wikipedia.org/wiki/Principle_of_least_privilege'>最小特权原则</a>，所有变量除了你计划去修改的都应该使用<code>const</code>。 基本原则就是如果一个变量不需要对它写入，那么其它使用这些代码的人也不能够写入它们，并且要思考为什么会需要对这些变量重新赋值。 使用 <code>const</code>也可以让我们更容易的推测数据的流动。</p><h2><a name='header-c569' class='md-header-anchor '></a>基本数据类型</h2><h3><a name='header-c570' class='md-header-anchor '></a>string类型</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>let sr1: string = `你是 ${ username }`</pre><h3><a name='header-c572' class='md-header-anchor '></a>数组</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>// 定义数组1：(定义数组中数据类型)
let ar1: Array&lt;number&gt; = [1,3,5,4]
// 定义数组2：泛型
let ar2: number[] = [1,2.3]
let ar3: string[] = [&#39;&#39;,&#39;&#39;]
// 定义数组3：元组(必须符合类型和数量)
let ar4: [number,string] = [10,&#39;jack&#39;]</pre><p>接口interface</p><ul><li>代替Object因为它基本不用</li></ul><pre class='md-fences mock-cm' style='display:block;position:relative'>// 1.1接口：(多次使用情况)
interface Person {
    name: string,
    age: number
}
// 1.2然后就可以类型重用了
let usr1: Person = {
    name: &#39;张文远&#39;,
    age: 20
}</pre><h3><a name='header-c581' class='md-header-anchor '></a>任意类型any</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>//（少用：不确定类型可以使用）
let usr2: any = 18
usr2 = &#39;吾人熊大大&#39;
let str8: string = (usr2 as string).substr(1) //2.2截取字符串</pre><h3><a name='header-c583' class='md-header-anchor '></a>数值型number</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>var age: number = 18</pre><p></p><h3><a name='header-c587' class='md-header-anchor '></a>补充：</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>类型除了用于变量声明还可以用于形参,后面是返回值类型
+ function add(x: number,y: number):number {
	return x+y
}
var ret: number = add(10,20)

也有没有返回值的函数
function fn(): void{
	console.log(&#39;hello&#39;)
}</pre><p></p><h2><a name='header-c591' class='md-header-anchor '></a>解构赋值</h2><h4><a name='header-c592' class='md-header-anchor '></a>数组按照顺序结构</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>// 数组,按照顺序解构
var arr = [2, 3];
var num1 = arr[0], num2 = arr[1], num3 = arr[2];
console.log([num1, num2, num3]);</pre><h4><a name='header-c594' class='md-header-anchor '></a>对象按照属性解构</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>// 对象，按照属性名解构
var userinfo = {
    name: &#39;zsfas&#39;,
    age: 18
};
// 在浏览器环境中，window有默认属性成员name
var nickname = userinfo.name, age = userinfo.age;
console.log(nickname);</pre><p>注意：</p><pre class='md-fences mock-cm' style='display:block;position:relative'>// 函数中形参不指定类型会默认any类型
function fn(x, y) {
    console.log(x + y);
}
fn(1, 5);</pre><h4><a name='header-c599' class='md-header-anchor '></a>剩余参数解构</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>function sum(..args: number[]){
	const ret = 0;
	args.forEach(function(item){
		ret += item
	})
	return ret
}
sum(1,2,3,4)
会动态推算出来返回值数据类型，
但前提是参数类型明确情况下
建议写上返回值类型！</pre><p></p><h2><a name='header-c603' class='md-header-anchor '></a>展开操作符</h2><h3><a name='header-c604' class='md-header-anchor '></a>数组展开操作符</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>// 数组展开操作符
let arr1 = [1,2.5,6]
let arr2 = [6,9,8,4,...arr1]//数组合并
console.log(arr2)
let arr3 = [...arr1,...arr2]//数组合并
console.log(arr3)</pre><h3><a name='header-c606' class='md-header-anchor '></a>对象展开操作符</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>// 对象展开操作符
// 对象的展开操作符，一般用于对象拷贝
var obj1 = {
    name: &#39;小艳艳&#39;,
    age: 28
}
var obj2 = {
    ...obj1,
    sex: &#39;女&#39;
}
console.log(obj2)</pre><h2><a name='header-c608' class='md-header-anchor '></a>类</h2><h3><a name='header-c609' class='md-header-anchor '></a>构造函数的另一张书写方式</h3><ul><li><p>ES6新增 的书写方式
传统方式：</p><pre class='md-fences mock-cm' style='display:block;position:relative'>function Person(name: string, age: number) {
    this.name = name
    this.age = age
}
Person.prototype.sayHello = function(){
    console.log(this.name,this.age)
}
let str = new Person(&#39;小艳艳&#39;,65)
str.sayHello()</pre></li><li><p>类写法</p><pre class='md-fences mock-cm' style='display:block;position:relative'>class Person {
    name: string
    age: number
       就是类的构造函数，当new Person时候，就会自动
	   调用constructor
    constructor(name: string, age: number) {
           这里实际上是在动态的为实例添加成员
	       TypeScript要求类的成员应该先被定义出来并确定类型
        this.name = name
        this.age = age
    }
       实例方法
    sayHello():void {
        console.log(this.name,this.age)
    }
}
let str = new Person(&#39;王艳&#39;,65)
str.sayHello()</pre></li></ul><h3><a name='header-c620' class='md-header-anchor '></a>类的继承</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>class Person {
    name: string
    age: number
    //就是类的构造函数，当new Person时候，就会自动
	//调用constructor
    constructor(name: string,age: number){
    	//这里实际上是在动态的为实例添加成员
	   //TypeScript要求类的成员应该先被定义出来并确定类型
        this.name = name
        this.age = age
    }
    //实例方法
    eat():void {
        console.log(&#39;米西米西&#39;)
    }
}
//继承
class Student extends Person {
    constructor(name: string,age: number) {
        //这是父类构造方法
        super(name,age)
    }
}
//调用
let p1 = new Student(&#39;伍云召&#39;,18)
p1.eat()</pre><p></p><h3><a name='header-c624' class='md-header-anchor '></a>类的简写形式</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>class info {
	name: string;
	age: number;
	constructor(name: string,age: number){
	    this.name = name
	    this.age = age
	}
}
改为：（成员比较少情况下）
class info {
	constructor(public name: string,public age: number){

	}
}
new info(&#39;阿吉&#39;,18,&#39;男&#39;)</pre><h2><a name='header-c626' class='md-header-anchor '></a>成员访问修饰符</h2><h4><a name='header-c627' class='md-header-anchor '></a><code>public</code> 开放的</h4><ul><li>默认为 <code>public</code></li></ul><pre class="md-fences md-end-block" lang="typescript"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">class</span> <span class="cm-def">Animal</span> {</span></pre></div><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-property">public</span> <span class="cm-def">name</span>: <span class="cm-variable-3">string</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-keyword">public</span> <span class="cm-variable">constructor</span>(<span class="cm-variable">theName</span>: <span class="cm-variable-3">string</span>) { <span class="cm-keyword">this</span>.<span class="cm-property">name</span> <span class="cm-operator">=</span> <span class="cm-variable">theName</span>; }</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-keyword">public</span> <span class="cm-variable">move</span>(<span class="cm-variable">distanceInMeters</span>: <span class="cm-variable-3">number</span>) {</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  <span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-string-2">`${</span><span class="cm-keyword">this</span>.<span class="cm-property">name</span><span class="cm-string-2">}</span> <span class="cm-string-2">moved ${</span><span class="cm-variable">distanceInMeters</span><span class="cm-string-2">}m.`</span>);</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  }</span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 168px;"></div></div></div></pre><h4><a name='header-c633' class='md-header-anchor '></a><code>private</code> 私有的</h4><ul><li>不能被外部访问，只能在类的内部访问使用</li><li>私有成员不会被继承</li></ul><pre class="md-fences md-end-block" lang="typescript"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">class</span> <span class="cm-def">userinfo</span>{</span></pre></div><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-property">name</span>: <span class="cm-variable-3">string</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-keyword">private</span> <span class="cm-variable">age</span>: <span class="cm-variable-3">number</span>;<span class="cm-comment">//私有成员，只能在类内部访问且不能被继承</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-keyword">protected</span> <span class="cm-variable">sex</span>: <span class="cm-variable-3">string</span> <span class="cm-operator">=</span> <span class="cm-string">'女'</span><span class="cm-comment">//受保护成员，也是私有的，外部不能被访问 但是可以被继承</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-variable">readonly</span> <span class="cm-variable">height</span>: <span class="cm-variable-3">number</span> <span class="cm-operator">=</span> <span class="cm-number">176</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-variable">fun</span>(){</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  <span class="cm-comment">//可以通过调用类内部方法的方式访问到私有成员</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  <span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-keyword">this</span>.<span class="cm-property">age</span>)</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  }</span></pre><pre class=""><span style="padding-right: 0.1px;"><span>​</span></span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 264px;"></div></div></div></pre><h4><a name='header-c642' class='md-header-anchor '></a><code>protected</code> 受保护的</h4><ul><li>和 <code>private</code> 类似，但是可以被继承</li></ul><pre class="md-fences md-end-block" lang="typescript"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">class</span> <span class="cm-def">inf</span> <span class="cm-keyword">extends</span> <span class="cm-variable">userinfo</span> {</span></pre></div><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-property">son</span>(){</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  <span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-keyword">this</span>.<span class="cm-property">sex</span>)<span class="cm-comment">//受保护成员，可以被继承</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  <span class="cm-variable">console</span>.<span class="cm-property">log</span>(<span class="cm-keyword">this</span>.<span class="cm-property">height</span>)</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  <span class="cm-keyword">this</span>.<span class="cm-property">name</span> <span class="cm-operator">=</span> <span class="cm-string">'阿花'</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  }</span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 168px;"></div></div></div></pre><p>注意，我们不能在 <code>Person</code>类外使用 <code>name</code>，但是我们仍然可以通过 <code>Employee</code>类的实例方法访问，因为<code>Employee</code>是由 <code>Person</code>派生而来的。</p><h4><a name='header-c650' class='md-header-anchor '></a><code>readonly</code> 只读的</h4><ul><li>只读 不允许修改,</li><li>作用： 和const定义的常量类似</li></ul><pre class='md-fences mock-cm' style='display:block;position:relative'>class inf extends userinfo {
    son(){
        console.log(this.sex)
        console.log(this.height)
        // this.height = 45 //只读属性 就是不能修改
        this.name = &#39;阿花&#39;
    }
}</pre><h2><a name='header-c659' class='md-header-anchor '></a>属性的存（get）取（set）器</h2><ul><li>用来校验属性</li></ul><pre class='md-fences mock-cm' style='display:block;position:relative'>class Person {
    private _age: number
    get age() { // 当访问 实例.fullName 的时候会调用 get 方法
        return this._age
    }
    set age(val) { // 当对 实例.fullName = xxx 赋值的时候会调用 set 方法
        if(val &lt; 0){
            throw new Error(&#39;年龄不能为负数&#39;)
        }
        this._age = val
    }
}
let p1 = new Person()
p1.age = 10
console.log(p1)</pre><h2><a name='header-c665' class='md-header-anchor '></a>类成员</h2><h3><a name='header-c666' class='md-header-anchor '></a>实例化成员</h3><ul><li>实例成员，只能通过new出来的实例访问</li></ul><h3><a name='header-c671' class='md-header-anchor '></a>静态成员</h3><ul><li><p>也叫类本身成员，只能通过类本身访问</p><pre class='md-fences mock-cm' style='display:block;position:relative'>// 实例成员，只能通过new出来的实例访问
// 静态成员，也叫类本身成员，只能通过类本身访问
class Persson{
	static type: string = &#39;asdf&#39;
	name: string = &#39;asd&#39;
}
Persson.type //静态成员只能类本身访问

// ---实例化成员只能 new 一个实例访问
new Persson().name 
Persson.name //不报错是因为构造函数本身具有这个默认属性</pre></li></ul><h1><a name='header-c677' class='md-header-anchor '></a>函数总结</h1><h2><a name='header-c678' class='md-header-anchor '></a>参数</h2><h3><a name='header-c679' class='md-header-anchor '></a>1、参数及返回值类型</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>function add(x: number, y: number): number {
	return x + y
}</pre><h3><a name='header-c681' class='md-header-anchor '></a>2、可选参数（y参数可传可不传）</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>function add(x: number, y?: number): number {
	return x + 10
}</pre><h3><a name='header-c683' class='md-header-anchor '></a>3、默认参数</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>function add(x: number, y: number = 20): number {
	return x + y
}</pre><h3><a name='header-c685' class='md-header-anchor '></a>4、剩余参数（不管传过来是什么，都存入数组）</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>function sum(...args: number[]): number {
	let ret: number = 0
	args.forEach((item: number): void =&gt; {
   	 ret += item
	})
	return ret
}
sum(1, 2, 3)</pre><h2><a name='header-c687' class='md-header-anchor '></a>箭头函数</h2><pre class='md-fences mock-cm' style='display:block;position:relative'>let add = (x: number,y: number):number ()=&gt; x+y</pre><h2><a name='header-c689' class='md-header-anchor '></a>for-of 循环</h2><h3><a name='header-c690' class='md-header-anchor '></a>常见循环：</h3><ul><li>例如：var array = [1,2,3,4,5,6,7]; </li></ul><ul><li><p>for 循环</p><pre class='md-fences mock-cm' style='display:block;position:relative'>for (var i = 0; i &lt; array.length; i) {  
    console.log(i,array[i]);  
}  </pre></li><li><p>forEach</p><ul><li><p>不支持 break</p><pre class='md-fences mock-cm' style='display:block;position:relative'>array.forEach(v=&gt;{  
    console.log(v);  
}); </pre></li></ul></li><li><p>for in</p><ul><li><p>会把数组当作对象来遍历</p><pre class='md-fences mock-cm' style='display:block;position:relative'>var A = {a:1,b:2,c:3,d:&quot;hello world&quot;};  
for(let k in A) {  
    console.log(k,A[k]);  
}  </pre></li></ul></li><li><p>for of</p><ul><li><p>支持 break</p><pre class='md-fences mock-cm' style='display:block;position:relative'>var A = {a:1,b:2,c:3,d:&quot;hello world&quot;};  
for(let k in A) {  
    console.log(k,A[k]);  
}  </pre></li></ul></li></ul><h1><a name='header-c725' class='md-header-anchor '></a>组件</h1><p>以下是一个最简单的 Angular 组件定义：</p><pre class="md-fences md-end-block" lang="javascript"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">import</span> { <span class="cm-def">Component</span> } <span class="cm-keyword">from</span> <span class="cm-string">'@angular/core'</span>;</span></pre></div><pre class=""><span style="padding-right: 0.1px;"><span>​</span></span></pre><pre class=""><span style="padding-right: 0.1px;">@<span class="cm-variable">Component</span>({</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">selector</span>: <span class="cm-string">'app-root'</span>,</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">templateUrl</span>: <span class="cm-string">'./app.component.html'</span>,</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">styleUrls</span>: [<span class="cm-string">'./app.component.css'</span>]</span></pre><pre class=""><span style="padding-right: 0.1px;">})</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">export</span> <span class="cm-keyword">class</span> <span class="cm-def">AppComponent</span> {</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">title</span> <span class="cm-operator">=</span> <span class="cm-string">'itcast'</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 240px;"></div></div></div></pre><ul><li><code>@Component</code>：这是一个 Decorator（装饰器），其作用类似于 Java 里面的注解。Decorator 这个语言特性目前（2017-10）处于 Stage 2（草稿）状态，还不是 ECMA 的正式规范。</li><li><code>selector</code>：组件的标签名，外部使用者可以这样来使用这个组件：<app-root>。默认情况下，ng 命令生成出来的组件都会带上一个 app 前缀，如果你不喜欢，可以在 angular-cli.json 里面修改 prefix 配置项，设置为空字符串将会不带任何前缀。</li><li><code>templateUrl</code>：引用外部的 HTML 模板。如果你想直接编写内联模板，可以使用 template，支持 ES6 引入的<a href='http://es6.ruanyifeng.com/#docs/string'>“模板字符串”写法</a>。</li><li><code>styleUrls</code>：引用外部 CSS 样式文件，这是一个数组，也就意味着可以引用多份 CSS 文件。</li><li><code>export class AppComponent</code>：这是 ES6 里面引入的模块和 class 定义方式。</li></ul><h2><a name='header-c745' class='md-header-anchor '></a>组件通信</h2><ul><li>直接的父子关系：父组件直接访问子组件的 public 属性和方法。</li><li>直接的父子关系：借助于 @Input 和 @Output 进行通讯</li><li>没有直接关系：借助于 Service 单例进行通讯。</li><li>利用 cookie 和 localstorage 进行通讯。</li><li>利用 session 进行通讯。</li><li>无论你使用什么前端框架，组件之间的通讯都离开不以上几种方案，这些方案与具体框架无关。</li></ul><h3><a name='header-c765' class='md-header-anchor '></a>父子通信：Input Down</h3><blockquote><p>参考文档：<a href='https://angular.io/guide/component-interaction#pass-data-from-parent-to-child-with-input-binding' target='_blank' >https://angular.io/guide/component-interaction#pass-data-from-parent-to-child-with-input-binding</a></p></blockquote><ol start='' ><li>父组件通过子组件标签传递属性</li><li>子组件在内部声明 <code>@Input</code> 接收</li></ol><ul><li><p>Input 是单向的</p><ul><li>父组件如果把数据改了，子组件也会更新</li><li>但是反之不会</li><li>有一个例外，引用类型修改</li></ul></li></ul><p>下面是一个示例：</p><p>子组件：</p><pre class="md-fences md-end-block" lang="typescript"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">import</span> { <span class="cm-def">Component</span>, <span class="cm-def">Input</span> } <span class="cm-keyword">from</span> <span class="cm-string">'@angular/core'</span>;</span></pre></div><pre class=""><span style="padding-right: 0.1px;"> </span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">import</span> { <span class="cm-def">Hero</span> } <span class="cm-keyword">from</span> <span class="cm-string">'./hero'</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;"> </span></pre><pre class=""><span style="padding-right: 0.1px;">@<span class="cm-variable">Component</span>({</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">selector</span>: <span class="cm-string">'app-hero-child'</span>,</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">template</span>: <span class="cm-string-2">`</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-string-2">&lt;h3&gt;{{hero.name}} says:&lt;/h3&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-string-2">&lt;p&gt;I, {{hero.name}}, am at your service, {{masterName}}.&lt;/p&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-string-2">`</span></span></pre><pre class=""><span style="padding-right: 0.1px;">})</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">export</span> <span class="cm-keyword">class</span> <span class="cm-def">HeroChildComponent</span> {</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-comment">// 声明接收父组件传递的数据</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  @<span class="cm-property">Input</span>() <span class="cm-variable">hero</span>: <span class="cm-variable">Hero</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">  @<span class="cm-property">Input</span>(<span class="cm-string">'master'</span>) <span class="cm-variable">masterName</span>: <span class="cm-variable-3">string</span>; <span class="cm-comment">// 接收 master 重命名为 masterName</span></span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 384px;"></div></div></div></pre><p>父组件：</p><pre class="md-fences md-end-block" lang="typescript"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">import</span> { <span class="cm-def">Component</span> } <span class="cm-keyword">from</span> <span class="cm-string">'@angular/core'</span>;</span></pre></div><pre class=""><span style="padding-right: 0.1px;"> </span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">import</span> { <span class="cm-def">HEROES</span> } <span class="cm-keyword">from</span> <span class="cm-string">'./hero'</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;"> </span></pre><pre class=""><span style="padding-right: 0.1px;">@<span class="cm-variable">Component</span>({</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">selector</span>: <span class="cm-string">'app-hero-parent'</span>,</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">template</span>: <span class="cm-string-2">`</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-string-2">&lt;h2&gt;{{master}} controls {{heroes.length}} heroes&lt;/h2&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-tab">    </span><span class="cm-string-2">&lt;!-- 在子组件标签上传递数据 --&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-string-2">&lt;app-hero-child *ngFor="let hero of heroes"</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; &nbsp;  <span class="cm-string-2">[hero]="hero"</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; &nbsp;  <span class="cm-string-2">[master]="master"&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-string-2">&lt;/app-hero-child&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-string-2">`</span></span></pre><pre class=""><span style="padding-right: 0.1px;">})</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">export</span> <span class="cm-keyword">class</span> <span class="cm-def">HeroParentComponent</span> {</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">heroes</span> <span class="cm-operator">=</span> <span class="cm-variable">HEROES</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-variable">master</span> <span class="cm-operator">=</span> <span class="cm-string">'Master'</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 456px;"></div></div></div></pre><h3><a name='header-c798' class='md-header-anchor '></a>父子通信：Output Up</h3><blockquote><p>参考文档：<a href='https://angular.io/guide/component-interaction#parent-listens-for-child-event' target='_blank' >https://angular.io/guide/component-interaction#parent-listens-for-child-event</a></p></blockquote><p><code>@Output</code> 的本质是事件机制，我们可以利用它来订阅子组件上发布的事件，子组件上这样写：</p><pre class="md-fences md-end-block" lang="typescript"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">import</span> { <span class="cm-def">Component</span>, <span class="cm-def">EventEmitter</span>, <span class="cm-def">Input</span>, <span class="cm-def">Output</span> } <span class="cm-keyword">from</span> <span class="cm-string">'@angular/core'</span>;</span></pre></div><pre class=""><span style="padding-right: 0.1px;"> </span></pre><pre class=""><span style="padding-right: 0.1px;">@<span class="cm-variable">Component</span>({</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">selector</span>: <span class="cm-string">'app-voter'</span>,</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">template</span>: <span class="cm-string-2">`</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-string-2">&lt;h4&gt;{{name}}&lt;/h4&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-string-2">&lt;button (click)="vote(true)"  [disabled]="voted"&gt;Agree&lt;/button&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-string-2">&lt;button (click)="vote(false)" [disabled]="voted"&gt;Disagree&lt;/button&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-string-2">`</span></span></pre><pre class=""><span style="padding-right: 0.1px;">})</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">export</span> <span class="cm-keyword">class</span> <span class="cm-def">VoterComponent</span> {</span></pre><pre class=""><span style="padding-right: 0.1px;">  @<span class="cm-variable">Input</span>()  <span class="cm-variable">name</span>: <span class="cm-variable-3">string</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">  @<span class="cm-variable">Output</span>() <span class="cm-variable">onVoted</span> <span class="cm-operator">=</span> <span class="cm-keyword">new</span> <span class="cm-variable">EventEmitter</span><span class="cm-operator">&lt;</span><span class="cm-variable-3">boolean</span><span class="cm-operator">&gt;</span>();</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-variable">voted</span> <span class="cm-operator">=</span> <span class="cm-atom">false</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;"> </span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-variable">vote</span>(<span class="cm-variable">agreed</span>: <span class="cm-variable-3">boolean</span>) {</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-keyword">this</span>.<span class="cm-property">onVoted</span>.<span class="cm-property">emit</span>(<span class="cm-variable">agreed</span>); <span class="cm-comment">// 传递的数据就是事件对象</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-keyword">this</span>.<span class="cm-property">voted</span> <span class="cm-operator">=</span> <span class="cm-atom">true</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">  }</span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 480px;"></div></div></div></pre><p>在父组件中订阅处理：</p><pre class="md-fences md-end-block" lang="typescript"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">import</span> { <span class="cm-def">Component</span> } &nbsp; &nbsp;  <span class="cm-keyword">from</span> <span class="cm-string">'@angular/core'</span>;</span></pre></div><pre class=""><span style="padding-right: 0.1px;"> </span></pre><pre class=""><span style="padding-right: 0.1px;">@<span class="cm-variable">Component</span>({</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">selector</span>: <span class="cm-string">'app-vote-taker'</span>,</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">template</span>: <span class="cm-string-2">`</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-string-2">&lt;h2&gt;Should mankind colonize the Universe?&lt;/h2&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-string-2">&lt;h3&gt;Agree: {{agreed}}, Disagree: {{disagreed}}&lt;/h3&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-string-2">&lt;app-voter *ngFor="let voter of voters"</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; &nbsp;  <span class="cm-string-2">[name]="voter"</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; &nbsp;  <span class="cm-string-2">(onVoted)="onVoted($event)"&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-string-2">&lt;/app-voter&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-tab">    </span><span class="cm-string-2">&lt;!-- $event在这里是自定义事件对象，接收到的是子组件内部发布事件传递的数据 --&gt;</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-string-2">`</span></span></pre><pre class=""><span style="padding-right: 0.1px;">})</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">export</span> <span class="cm-keyword">class</span> <span class="cm-def">VoteTakerComponent</span> {</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-property">agreed</span> <span class="cm-operator">=</span> <span class="cm-number">0</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-variable">disagreed</span> <span class="cm-operator">=</span> <span class="cm-number">0</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-variable">voters</span> <span class="cm-operator">=</span> [<span class="cm-string">'Mr. IQ'</span>, <span class="cm-string">'Ms. Universe'</span>, <span class="cm-string">'Bombasto'</span>];</span></pre><pre class=""><span style="padding-right: 0.1px;"> </span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-variable">onVoted</span>(<span class="cm-variable">agreed</span>: <span class="cm-variable-3">boolean</span>) {</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-variable">agreed</span> <span class="cm-operator">?</span> <span class="cm-keyword">this</span>.<span class="cm-property">agreed</span><span class="cm-operator">++</span> : <span class="cm-keyword">this</span>.<span class="cm-property">disagreed</span><span class="cm-operator">++</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">  }</span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 552px;"></div></div></div></pre><h3><a name='header-c808' class='md-header-anchor '></a>父子通信：父组件直接访问子组件 public 成员</h3><blockquote><p>参考文档：<a href='https://angular.io/guide/component-interaction#parent-interacts-with-child-via-local-variable' target='_blank' >https://angular.io/guide/component-interaction#parent-interacts-with-child-via-local-variable</a></p></blockquote><p>对于有直接父子关系的组件，父组件可以直接访问子组件里面 public 型的属性和方法，示例代码片段如下：</p><pre class="md-fences md-end-block" lang="html"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-tag cm-bracket">&lt;</span><span class="cm-tag">app-foo</span> <span class="cm-attribute">#child</span><span class="cm-tag cm-bracket">&gt;&lt;/</span><span class="cm-tag">app-foo</span><span class="cm-tag cm-bracket">&gt;</span></span></pre></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-tag cm-bracket">&lt;</span><span class="cm-tag">button</span> <span class="cm-attribute">(click)</span>=<span class="cm-string">"child.increment()"</span><span class="cm-tag cm-bracket">&gt;</span>调用子组件的方法<span class="cm-tag cm-bracket">&lt;/</span><span class="cm-tag">button</span><span class="cm-tag cm-bracket">&gt;</span></span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 48px;"></div></div></div></pre><p>显然，子组件里面必须暴露一个 public 型的 childFn 方法，就像这样：</p><pre class="md-fences md-end-block" lang="typescript"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">export</span> <span class="cm-keyword">class</span> <span class="cm-def">FooComponent</span> <span class="cm-keyword">implements</span> <span class="cm-variable">OnInit</span> {</span></pre></div><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-keyword">public</span> <span class="cm-variable">message</span>: <span class="cm-variable-3">string</span> <span class="cm-operator">=</span> <span class="cm-string">'foo message'</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-keyword">public</span> <span class="cm-variable">count</span>: <span class="cm-variable-3">number</span> <span class="cm-operator">=</span> <span class="cm-number">0</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span>​</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-variable">constructor</span>() { }</span></pre><pre class=""><span style="padding-right: 0.1px;"><span>​</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-keyword">public</span> <span class="cm-variable">increment</span> (): <span class="cm-variable">void</span> {</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  <span class="cm-keyword">this</span>.<span class="cm-property">count</span><span class="cm-operator">++</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  }</span></pre><pre class=""><span style="padding-right: 0.1px;"><span>​</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-variable">ngOnInit</span>() {</span></pre><pre class=""><span style="padding-right: 0.1px;">  }</span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 312px;"></div></div></div></pre><p>以上是通过在模板里面定义局部变量的方式来直接调用子组件里面的 public 型方法。在父组件的内部也可以访问到子组件的实例，需要利用到 @ViewChild 装饰器，示例如下：</p><pre class="md-fences md-end-block" lang="typescript"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;">@<span class="cm-variable">ViewChild</span>(<span class="cm-variable">ChildComponent</span>)</span></pre></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">private</span> <span class="cm-variable">childComponent</span>: <span class="cm-variable">ChildComponent</span>;</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 48px;"></div></div></div></pre><p>关于 @ViewChild 在后面的内容里面会有更详细的解释。</p><p>很明显，如果父组件直接访问子组件，那么两个组件之间的关系就被固定死了。父子两个组件紧密依赖，谁也离不开谁，也就都不能单独使用了。所以，除非你知道自己在做什么，最好不要直接在父组件里面直接访问子组件上的属性和方法，以免未来一改一大片。</p><h2><a name='header-c825' class='md-header-anchor '></a>组件生命周期</h2><ul><li><p>ngOnChanges()</p></li><li><p>ngOnInit()</p><ul><li>只执行一次</li></ul></li><li><p>ngDoCheck()</p></li><li><p>ngAfterContentInit()</p><ul><li>只执行一次</li></ul></li><li><p>ngAfterContentChecked()</p></li><li><p>ngAfterViewInit()</p><ul><li>只执行一次</li></ul></li><li><p>ngAfterViewChecked()</p></li><li><p>ngOnDestroy()</p><ul><li>只执行一次</li></ul></li></ul><ul><li>Angular 一共暴露了8个“钩子”，构造函数不算。</li><li>并没有组件或者指令会实现全部钩子。</li><li>绿色的4个钩子可能会被执行很多次，紫色的只会执行一次。</li><li>Content 和 View 相关的4个钩子只对组件有效，指令上不能使用。因为在新版本的 Angular 里面，指令不能带有 HTML 模板。指令没有自己的 UI，当然就没有 View 和 Content 相关的“钩子”了。</li><li>请不要在生命周期钩子里面实现复杂的业务逻辑，尤其是那4个会被反复执行的钩子，否则一定会造成界面卡顿。</li></ul><h2><a name='header-c883' class='md-header-anchor '></a>动态组件</h2><blockquote><p>参考文档：<a href='https://angular.io/guide/dynamic-component-loader' target='_blank' >https://angular.io/guide/dynamic-component-loader</a></p></blockquote><p>!&gt; <strong>注意：用代码动态创建组件这种方式在一般的业务开发里面不常用，而且可能存在一些隐藏的坑，如果你一定要用，请小心避雷。</strong></p><p></p><h1><a name='header-c891' class='md-header-anchor '></a>TodoMVC案例介绍</h1><h2><a name='header-c892' class='md-header-anchor '></a>起步</h2><p>下载模板：</p><pre class="md-fences md-end-block" lang="shell"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-builtin">git</span> clone https://github.com/tastejs/todomvc-app-template.git <span class="cm-attribute">--depth</span> 1</span></pre></div></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 24px;"></div></div></div></pre><p>初始化项目：</p><pre class="md-fences md-end-block" lang="shell"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;">ng new todomvc-angular</span></pre></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-builtin">cd</span> todomvc-angular</span></pre><pre class=""><span style="padding-right: 0.1px;">ng serve</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 72px;"></div></div></div></pre><p>将 <code>todomvc-angular\src\app\app.component.html</code> 文件内容替换如下：</p><pre class='md-fences mock-cm' style='display:block;position:relative'>&lt;section class=&quot;todoapp&quot;&gt;
  &lt;header class=&quot;header&quot;&gt;
    &lt;h1&gt;todos&lt;/h1&gt;
    &lt;input class=&quot;new-todo&quot; placeholder=&quot;What needs to be done?&quot; autofocus&gt;
  &lt;/header&gt;
  &lt;!-- This section should be hidden by default and shown when there are todos --&gt;
  &lt;section class=&quot;main&quot;&gt;
    &lt;input id=&quot;toggle-all&quot; class=&quot;toggle-all&quot; type=&quot;checkbox&quot;&gt;
    &lt;label for=&quot;toggle-all&quot;&gt;Mark all as complete&lt;/label&gt;
    &lt;ul class=&quot;todo-list&quot;&gt;
      &lt;!-- These are here just to show the structure of the list items --&gt;
      &lt;!-- List items should get the class `editing` when editing and `completed` when marked as completed --&gt;
      &lt;li class=&quot;completed&quot;&gt;
        &lt;div class=&quot;view&quot;&gt;
          &lt;input class=&quot;toggle&quot; type=&quot;checkbox&quot; checked&gt;
          &lt;label&gt;Taste JavaScript&lt;/label&gt;
          &lt;button class=&quot;destroy&quot;&gt;&lt;/button&gt;
        &lt;/div&gt;
        &lt;input class=&quot;edit&quot; value=&quot;Create a TodoMVC template&quot;&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;div class=&quot;view&quot;&gt;
          &lt;input class=&quot;toggle&quot; type=&quot;checkbox&quot;&gt;
          &lt;label&gt;Buy a unicorn&lt;/label&gt;
          &lt;button class=&quot;destroy&quot;&gt;&lt;/button&gt;
        &lt;/div&gt;
        &lt;input class=&quot;edit&quot; value=&quot;Rule the web&quot;&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/section&gt;
  &lt;!-- This footer should hidden by default and shown when there are todos --&gt;
  &lt;footer class=&quot;footer&quot;&gt;
    &lt;!-- This should be `0 items left` by default --&gt;
    &lt;span class=&quot;todo-count&quot;&gt;&lt;strong&gt;0&lt;/strong&gt; item left&lt;/span&gt;
    &lt;!-- Remove this if you don&#39;t implement routing --&gt;
    &lt;ul class=&quot;filters&quot;&gt;
      &lt;li&gt;
        &lt;a class=&quot;selected&quot; href=&quot;#/&quot;&gt;All&lt;/a&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;a href=&quot;#/active&quot;&gt;Active&lt;/a&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;a href=&quot;#/completed&quot;&gt;Completed&lt;/a&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
    &lt;!-- Hidden if no completed items are left ↓ --&gt;
    &lt;button class=&quot;clear-completed&quot;&gt;Clear completed&lt;/button&gt;
  &lt;/footer&gt;
&lt;/section&gt;
&lt;footer class=&quot;info&quot;&gt;
  &lt;p&gt;Double-click to edit a todo&lt;/p&gt;
  &lt;!-- Remove the below line ↓ --&gt;
  &lt;p&gt;Template by &lt;a href=&quot;http://sindresorhus.com&quot;&gt;Sindre Sorhus&lt;/a&gt;&lt;/p&gt;
  &lt;!-- Change this out with your name and url ↓ --&gt;
  &lt;p&gt;Created by &lt;a href=&quot;http://todomvc.com&quot;&gt;you&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;Part of &lt;a href=&quot;http://todomvc.com&quot;&gt;TodoMVC&lt;/a&gt;&lt;/p&gt;
&lt;/footer&gt;</pre><p>安装模板依赖的样式文件：</p><pre class="md-fences md-end-block" lang="shell"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-builtin">npm</span> install todomvc-app-css</span></pre></div></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 24px;"></div></div></div></pre><p>在 <code>todomvc-angular\src\styles.css</code> 文件中导入样式文件：</p><pre class="md-fences md-end-block" lang="css"> <div class="CodeMirror cm-s-inner CodeMirror-wrap"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 4px;"></div><div class="CodeMirror-hscrollbar" style="left: 0px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar"><div style="min-width: 1px; height: 0px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment">/*自动引入第三方包，不用写完整路径*/</span></span></pre></div><pre class=""><span style="padding-right: 0.1px;"><span class="cm-def">@import</span> <span class="cm-tag">url</span>(<span class="cm-string">'todomvc-app-css/index.css'</span>);</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-def">@import</span> <span class="cm-tag">url</span>(<span class="cm-string">'todomvc-common/base.css'</span>);</span></pre></div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 0px;"></div><div class="CodeMirror-gutters" style="display: none; height: 72px;"></div></div></div></pre><p>看到如下页面说明成功。、</p><p><img src='./md%E6%96%87%E6%A1%A3%E5%9B%BE%E7%89%87/todomvcr.png' alt='' /></p><p></p><h2><a name='header-c914' class='md-header-anchor '></a>模拟</h2><p>在组件中自定义数据自定义数据：</p><pre class='md-fences mock-cm' style='display:block;position:relative'>const conds = [
  { id: 1, title: &#39;吃饭&#39;, done: true },
  { id: 2, title: &#39;睡觉&#39;, done: true },
  { id: 3, title: &#39;唱歌&#39;, done: false },
  { id: 4, title: &#39;看书&#39;, done: true },
]</pre><h4><a name='header-c918' class='md-header-anchor '></a>1、页面判断有数据处理：</h4><h5><a name='header-c919' class='md-header-anchor '></a>暴露数据：</h5><pre class='md-fences mock-cm' style='display:block;position:relative'>export class AppComponent {
  public todos: {
    id: number,
    title: string,
    done: boolean
}[] = conds;</pre><h5><a name='header-c921' class='md-header-anchor '></a>循环生成li</h5><ul><li><p>每个li有三种状态：</p></li><li><p>正常（没有样式）、完成（completed）、编辑（editing）</p><pre class='md-fences mock-cm' style='display:block;position:relative'>&lt;li *ngFor=&quot;let todo of todos&quot;&gt;
{{todo.title}}
&lt;/li&gt;</pre></li></ul><h5><a name='header-c930' class='md-header-anchor '></a>无数据时处理：</h5><ul><li><p>条件渲染：（当没有数据时，footer不显示）</p><pre class='md-fences mock-cm' style='display:block;position:relative'>&lt;footer class=&quot;footer&quot; *ngIf=&quot;todos.length&quot;&gt;
&lt;/footer&gt;</pre></li></ul><h5><a name='header-c936' class='md-header-anchor '></a>使用angluar模版标签渲染(推荐)</h5><pre class='md-fences mock-cm' style='display:block;position:relative'>//直接使用将整个标签包裹起来
&lt;ng-template [ngIf]=&quot;todos.length&quot;&gt;
&lt;ng-template&gt;
这样可以统一处理，只有当有数据时，才会渲染列表项和底部</pre><h5><a name='header-c938' class='md-header-anchor '></a>添加任务：</h5><ul><li><p>输入内容+回车=&gt;添加列表项目</p><pre class='md-fences mock-cm' style='display:block;position:relative'>1、先给文本框注册（keyup）事件
(keyup) = &quot;addTo($event)&quot; //$event表示事件对象

然后在组件.ts文件中注册添加方法
 addTo(e) {
    const titleText = e.target.value
    if (!titleText.length) {
      return
    }
    if (e.keyCode == 13) {//点击enter键时触发
      const txtInfo = e.target.value;
      const last = this.todos[this.todos.length - 1];
      this.todos.push({
        id: last ? last.id + 1 : 1, //注意，判断时并没有id
        title: txtInfo,
        done: false
      })
      //同时清空文本框内容
      e.target.value = &#39;&#39;
      console.log(this.todos)
    }
  }</pre><p>​</p></li></ul><h1><a name='header-c946' class='md-header-anchor '></a>利用双向绑定显示任务完成状态</h1><ul><li>去掉勾选（完成及未完成状态）</li></ul><p>注意：</p><ul><li><p>使用 ngModel 必须导入FormsModule 并把它添加到 Angular 模块的 imports 列表中。</p><pre class='md-fences mock-cm' style='display:block;position:relative'>module.ts中：
import { FormsModule } from &#39;@angular/forms&#39;;@NgModule({
declarations: [
  AppComponent
],
imports: [
  BrowserModule,
  FormsModule		//添加到 Angular 模块的 imports 列表中。
],
providers: [],
bootstrap: [AppComponent]
})</pre></li><li><p>然后页面就可以使用双向绑定了</p><pre class='md-fences mock-cm' style='display:block;position:relative'>&lt;input  class=&quot;toggle&quot; type=&quot;checkbox&quot; 

  [(ngModel)] = &quot;todo.done&quot;&gt;</pre></li></ul><h2><a name='header-c962' class='md-header-anchor '></a>ngClass处理样式style</h2><pre class='md-fences mock-cm' style='display:block;position:relative'>&lt;li&gt;
&lt;a [ngClass]=&quot;{selected:visiblity == &#39;all&#39;}&quot; 
href=&quot;#/&quot;&gt;显示所有任务&lt;/a&gt;
&lt;/li&gt;</pre><h2><a name='header-c964' class='md-header-anchor '></a>知识点</h2><h4><a name='header-c965' class='md-header-anchor '></a>1、通过every遍历查找数据</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>get toggleAll () {
//找出并返回符合条件的数据
return this.todos.every(t =&gt; t.done)
}</pre><h4><a name='header-c967' class='md-header-anchor '></a>2、双击事件</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>&lt;label (dblclick) = &quot;currentEditing = todo&quot;&gt;{{ todo.title }}&lt;/label&gt;</pre><h4><a name='header-c969' class='md-header-anchor '></a>3、文本框内容：</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>[value]=&quot;todo.title&quot;</pre><h4><a name='header-c971' class='md-header-anchor '></a>4、enter按钮事件/esc按钮</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>(keyup.enter) = &quot;seveEdit($event,i)&quot;
(keyup.esc) = &quot;escEdit()&quot;</pre><h4><a name='header-c973' class='md-header-anchor '></a>5、filter遍历对象数组</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>//返回所有未完成
return this.todos.filter(t =&gt; !t.done)</pre><h4><a name='header-c975' class='md-header-anchor '></a>6、锚点改变事件</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>监听锚点事件
window.onhashchange = function () {
let index = location.href.lastIndexOf(&quot;#&quot;)
// 获取锚点值
let asd = location.href.slice(index + 2)
console.log(location.href.slice(index + 2))
// console.log(location.href.)
}</pre><h3><a name='header-c977' class='md-header-anchor '></a>数据过滤</h3><ul><li><p>1、提供一个属性，该属性会根据当前点击的链接返回过滤之后的数据</p><p>  get filterTodos() {
   if (this.visiblity == &#39;all&#39;) {</p><pre class='md-fences mock-cm' style='display:block;position:relative'>  return this.todos;
} else if (this.visiblity == &#39;active&#39;) {
  //返回所有未完成
  return this.todos.filter(t =&gt; !t.done)
} else if (this.visiblity == &#39;completed&#39;) {
  //返回所有完成
  return this.todos.filter(t =&gt; t.done)
}</pre><p>  }</p></li><li><p>2、提供一个属性，用来存储当前点击链接的标识（visiblity）是一个字符串：</p><p>  hashchangeHandle() {
  	//获取当前锚点值，参数1 只是截取的  意思</p><pre class='md-fences mock-cm' style='display:block;position:relative'>const hash = window.location.hash.substr(1);
switch (hash) {
  case &#39;/&#39;:
    this.visiblity = &#39;all&#39;;
    break;
  case &#39;/active&#39;:
    this.visiblity = &#39;active&#39;;
    break;
  case &#39;/completed&#39;:
    this.visiblity = &#39;completed&#39;;
    break;
}</pre><p>  }
​</p></li><li><p>3、为链接添加点击事件，当点击导航链接时，改变visiblity标识</p><p>  <li>
  	&lt;a </p><pre class='md-fences mock-cm' style='display:block;position:relative'> [ngClass]=&quot;{selected:visiblity == &#39;completed&#39;}&quot;
 href=&quot;#/completed&quot;&gt;已完成任务&lt;/a&gt;</pre><p>  </li></p></li><li><p>用户动态点击了锚点的时候，我们需要获取当前锚点的标识然后动态的将根组件中的visibility设置为当前点击的锚点标识</p><p>  生命钩子（生命周期函数）
  ngOnInit() {//在初始化时候执行一次</p><pre class='md-fences mock-cm' style='display:block;position:relative'>this.hashchangeHandle()
//每次锚点改变时调用一次
window.onhashchange = this.hashchangeHandle.bind(this)//必须改变this指向，否则将指向window
// 这样就能当页面刷新时，依然保持过滤状态、</pre><p>  }</p></li></ul><h3><a name='header-c1008' class='md-header-anchor '></a>持久化存储在本地</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>生命周期钩子函数
ngDoCheck(){//当组件数据放生改变时，会触发
 //在钩子函数中存储数据
 window.localStorage.setItem(&#39;todos&#39;,JSON.stringify(this.todos))
}</pre><h1><a name='header-c1018' class='md-header-anchor '></a>通讯录案例</h1><h2><a name='header-c1019' class='md-header-anchor '></a>知识点：</h2><h3><a name='header-c1020' class='md-header-anchor '></a>1、创建组件</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>ng g component navabar(组件名)</pre><h3><a name='header-c1022' class='md-header-anchor '></a>2、导入样式</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>安装
cnpm i bootstrap@3 -S
导入样式(项目根路径下style.css)
@import url(&quot;bootstrap/dist/css/bootstrap.min.css&quot;);</pre><h3><a name='header-c1024' class='md-header-anchor '></a>3、使用路由功能</h3><h4><a name='header-c1025' class='md-header-anchor '></a>安装</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>1、添加路由模块（AppRoutingModule）
ng generate module app-routing --flat --module=app
挥动在app目录下生成路由文件：app-routing.module.ts</pre><h4><a name='header-c1027' class='md-header-anchor '></a>配置路由</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>配置路由出口及路由导航链接
import { RouterModule, Routes } from &#39;@angular/router&#39;;</pre><h4><a name='header-c1029' class='md-header-anchor '></a>导入路由组件</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>import { SiginComponent } from &#39;./sigin/sigin.component&#39;
import { SiginupComponent } from &#39;./siginup/siginup.component&#39;</pre><h4><a name='header-c1031' class='md-header-anchor '></a>设置路由导航数组对象（路由表）</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>const routes: Routes = [
  {
path: &#39;sigin&#39;,
component: SiginComponent 
},
{
path: &#39;siginup&#39;,
component: SiginupComponent 
}]</pre><h4><a name='header-c1033' class='md-header-anchor '></a>设置路由出口</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>&lt;!--设置路由出口：--&gt;
&lt;router-outlet&gt;&lt;/router-outlet&gt;</pre><h4><a name='header-c1035' class='md-header-anchor '></a>设置导航链接</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>&lt;ul&gt;
  &lt;li&gt;
&lt;a routerLink=&quot;/sigin&quot;&gt;Go Foo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a routerLink=&quot;/siginup&quot;&gt;Go Foo&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;</pre><h3><a name='header-c1037' class='md-header-anchor '></a>嵌套路由</h3><h4><a name='header-c1038' class='md-header-anchor '></a>1、视情况自行安装一个组建</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>ng g component layout
//将主页代码，放入layout.html中
//配置用户列表路由</pre><p>2、嵌套路由，先导入用户列表组件</p><pre class='md-fences mock-cm' style='display:block;position:relative'>import { ComtactListComponent } from &#39;./comtact-list/comtact-list.component&#39;</pre><p>3、再配置路由表：</p><pre class='md-fences mock-cm' style='display:block;position:relative'>{
    path: &#39;comtact&#39;,
    component: LayoutComponent,
    children: [
      {
        path: &#39;&#39;,
        component: ComtactListComponent
      }
    ]
 }</pre><h3><a name='header-c1046' class='md-header-anchor '></a>拓展：重定向</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>{//配置重定向
    path: &#39;&#39;,
    redirectTo: &#39;/comtact&#39;,//当请求根路径时，跳转到ComtactListComponent组件
    pathMatch: &#39;full&#39;    //必须设置完全匹配时才做重定向
}</pre><h3><a name='header-c1048' class='md-header-anchor '></a>双向绑定</h3><pre class='md-fences mock-cm' style='display:block;position:relative'>之前app主组件已经配置了双向绑定，那么子组件就不用配置了，直接用即可
[(ngModel)] = &quot;singinupForm.email&quot;
[(ngModel)] = &quot;singinupForm.password&quot;
//双向绑定数据的表单要设置name属性</pre><h3><a name='header-c1050' class='md-header-anchor '></a>表单验证：</h3><ul><li><p>angluar提交表单时默认验证失效；</p></li><li><p>可以通过模版引擎变量：#email</p></li><li><p>访问当前作用的类样式</p><pre class='md-fences mock-cm' style='display:block;position:relative'>	  &lt;input 
      type=&quot;email&quot; 
      id=&quot;inputEmail&quot; 
      name=&quot;email&quot;
      class=&quot;form-control&quot; 
      placeholder=&quot;Email address&quot; 
      required  //属性规定必需在提交之前填写输入字段。如果使用该属性，则字段是必填（或必选）的。
      #email
      email = &#39;true&#39; //开启验证
      [(ngModel)] = &quot;siginupFrom.email&quot;&gt;
   	  &lt;div [hidden]=&quot;email.valid || email.pristine&quot;
        class=&quot;alert alert-danger&quot;&gt;
        邮箱不能为空！
      &lt;/div&gt;</pre></li></ul><h4><a name='header-c1062' class='md-header-anchor '></a>原理：</h4><h5><a name='header-c1063' class='md-header-anchor '></a>1、angluar表单双向绑定会为表单提供特殊类名</h5><pre class='md-fences mock-cm' style='display:block;position:relative'>State			         Class if true		 Class if false		
表单是否被碰过				ng-touched			ng-untouched		
表单是否已经被输入数据了	ng-dirty			 ng-pristine		
表单是否有效			     ng-valid			 ng-invalid</pre><p>2、通过添加样式类名：设置验证样式（style.css ）：</p><pre class='md-fences mock-cm' style='display:block;position:relative'>++验证失败样式
.ng-valid[required], .ng-valid.required  {
  border-left: 5px solid #42A948; /* green */
}
++验证成功样式
.ng-invalid:not(form)  {
  border-left: 5px solid #a94442; /* red */
}</pre><h4><a name='header-c1068' class='md-header-anchor '></a>判断是否为空</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>//无效的，并且被输入数据，被碰过的
&lt;div *ngIf=&quot;email.invalid &amp;&amp; (email.dirty || email.touched)&quot;
            class=&quot;alert alert-danger&quot;&gt;
        &lt;div *ngIf=&quot;email.errors.required&quot;&gt;
             邮箱不能为空！
        &lt;/div&gt;
        &lt;div *ngIf=&quot;email.errors.email&quot;&gt;
             无效邮箱！
        &lt;/div&gt;
&lt;/div&gt;</pre><h4><a name='header-c1070' class='md-header-anchor '></a>禁用提交按钮</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>form设置
#formMy = &quot;ngForm&quot;

提交按钮上：
[disabled]=&quot;!formMy.form.valid&quot;//验证不通过，按钮禁用</pre><h4><a name='header-c1072' class='md-header-anchor '></a>验证输入长度</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>//元素设置长度属性
minlength=&quot;6&quot;
maxlength=&quot;12&quot;

&lt;div *ngIf=&quot;password.invalid &amp;&amp; (password.dirty || password.touched)&quot;
            class=&quot;alert alert-danger&quot;&gt;
        &lt;div *ngIf=&quot;password.errors.required&quot;&gt;
             密码不能为空！
        &lt;/div&gt;
        &lt;div *ngIf=&quot;password.errors.minlength&quot;&gt;
             密码不能少于6位！
        &lt;/div&gt;
        &lt;div *ngIf=&quot;password.errors.maxlength&quot;&gt;
             密码不能大于12位！
        &lt;/div&gt;
&lt;/div&gt;</pre><h3><a name='header-c1074' class='md-header-anchor '></a>接口</h3><h4><a name='header-c1075' class='md-header-anchor '></a>导入http服务模块（app主组件）</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>import{ HttpClientModule } from &#39;@angluar/common/http&#39;</pre><h4><a name='header-c1077' class='md-header-anchor '></a>开启http服务</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    HttpClientModule
  ],</pre><h4><a name='header-c1079' class='md-header-anchor '></a>子组件模块中：</h4><h5><a name='header-c1080' class='md-header-anchor '></a>1、导入http模块</h5><pre class='md-fences mock-cm' style='display:block;position:relative'>import { HttpClient } from &#39;@angular/common/http&#39;;</pre><p>2、回调函数</p><pre class='md-fences mock-cm' style='display:block;position:relative'>// 组建类中声明了私有成员http,它的类型是HttpClient
// angluar 会自动去实例化 HttpClient 得到一个实例
// 然后就可以在组件中使用http这个成员来调用一些请求方法了
constructor(
	private http: HttpClient
){ }</pre><h5><a name='header-c1085' class='md-header-anchor '></a>3、测试使用</h5><pre class='md-fences mock-cm' style='display:block;position:relative'>const formDta = this.signupFrom //获取数据
siginup(){
	this.http.post(&#39;http://localhost:3000/users&#39;,formDta)  //戴尔请求
	.toPrromise().then(data =&gt; {
	})
}</pre><p></p><h3><a name='header-c1089' class='md-header-anchor '></a>跳转</h3><h4><a name='header-c1090' class='md-header-anchor '></a>1、引入路由模块</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>import { Router } from &quot;@angular/router&quot;</pre><h4><a name='header-c1092' class='md-header-anchor '></a>2、启用路由</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>constructor(
    private http: HttpClient,
    private router: Router
  ) { }</pre><h4><a name='header-c1094' class='md-header-anchor '></a>3、router.navigate跳转至首页</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>this.router.navigate([&#39;/&#39;]) //跳转到首页</pre><h3><a name='header-c1096' class='md-header-anchor '></a>使用路由守卫拦截保护权</h3><h4><a name='header-c1097' class='md-header-anchor '></a>1、app目录下新建:auth-guard.service.ts 文件：</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>载入：
import { Injectable } from &#39;@angular/core&#39;;
import { CanActivate, Router } from &#39;@angular/router&#39;;
@Injectable()
export class AuthGuard implements CanActivate {
    constructor(
        private router: Router
    ) { }
    canActivate() {
    	//获取权限信息
        const token = window.localStorage.getItem(&quot;auth_token&quot;)
        if (!token) {
            this.router.navigate([&#39;/sigin&#39;])
            return false //如果为空不能继续导航
        }//规避登录页面华北地区登录情况
        return true; //有权限则继续导航
    }
}</pre><h4><a name='header-c1099' class='md-header-anchor '></a>2、在app.router文件中引入 路由守卫</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>//导入路由守卫
import { AuthGuard } from &quot;./auth-guard.service&quot;

路由中新增（providers）属性：
@NgModule({
  imports: [
    RouterModule.forRoot(routes)
  ],
  exports: [RouterModule],
  providers: [AuthGuard]
})</pre><h3><a name='header-c1101' class='md-header-anchor '></a>Http拦截器</h3><h4><a name='header-c1102' class='md-header-anchor '></a>1、app目录下新建global.interceptor.ts //通用的拦截器</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>直接载入官方代码：
import { Injectable } from &#39;@angular/core&#39;;
import {
  HttpEvent, HttpInterceptor, HttpHandler, HttpRequest
} from &#39;@angular/common/http&#39;;

import { Observable } from &#39;rxjs&#39;;

/** Pass untouched request through to the next request handler. */
@Injectable()
export class GlobalNoopInterceptor  implements HttpInterceptor {

  intercept(req: HttpRequest&lt;any&gt;, next: HttpHandler):
    Observable&lt;HttpEvent&lt;any&gt;&gt; {
    console.log(&quot;所有请求都会经过这里&quot;)
    const token = window.localStorage.getItem(&#39;auth_token&#39;)
    const authReq = req.clone({
      headers: req.headers.set(&#39;X-Access-Token&#39;, token),
    });
    // 获取请求类型
    //当请求类型为登录或者注册时，不用返回，请求头，避免登录或者注册失败
    var urlrouter = location.href.substr(location.href.lastIndexOf(&#39;/&#39;)+1)
    console.log(urlrouter)
    if(urlrouter == &#39;sigin&#39; || urlrouter ==&#39;siginup&#39;) {
      return next.handle(req);
    } else {
      return next.handle(authReq);
    }
  }
}
</pre><h4><a name='header-c1104' class='md-header-anchor '></a>2、根模块app.module.ts中，引入启用拦截功能：</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>//导入http拦截器
import { GlobalNoopInterceptor } from &quot;./global.interceptor&quot;
import { HTTP_INTERCEPTORS } from &quot;@angular/common/http&quot;


配置
providers: [{
    provide: HTTP_INTERCEPTORS, 
    useClass: GlobalNoopInterceptor, 
    multi: true 
  }],</pre><p></p><p>接下来就可以在拦截器中，设置想要的行为</p><p>注意：</p><ul><li>// 获取请求类型</li><li>// 当请求类型为登录或者注册时，不用返回，请求头，避免登录或者注册</li><li>// 失败</li></ul><pre class='md-fences mock-cm' style='display:block;position:relative'>// 获取请求类型
    //当请求类型为登录或者注册时，不用返回，请求头，避免登录或者注册失败
    var urlrouter = location.href.substr(location.href.lastIndexOf(&#39;/&#39;)+1)
    console.log(urlrouter)
    if(urlrouter == &#39;sigin&#39; || urlrouter ==&#39;siginup&#39;) {
      return next.handle(req);
    } else {
      return next.handle(authReq);
    }</pre><h3><a name='header-c1123' class='md-header-anchor '></a>知识点：</h3><h4><a name='header-c1124' class='md-header-anchor '></a>1、清除a标签默认行为；</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>even.preventDefault();//取消默认样式</pre><h4><a name='header-c1126' class='md-header-anchor '></a>2、提示是否删除？</h4><pre class='md-fences mock-cm' style='display:block;position:relative'>if(!window.confirm(&#39;是否删除用户&#39;)){
	return
}</pre><p></p><h3><a name='header-c1130' class='md-header-anchor '></a>编辑用户</h3><p>1、编辑路由改为动态路径</p><pre class='md-fences mock-cm' style='display:block;position:relative'>&lt;a [routerLink]=&quot;[&#39;/comtact/edit&#39;,item.id]&quot;&gt;编辑&lt;/a&gt;</pre><p>2、编辑值动态的</p><pre class='md-fences mock-cm' style='display:block;position:relative'>[routerLink]=&quot;[&#39;/comtact/edit&#39;,item.id]&quot;</pre><p>3、如何在编辑组件中获取动态参数</p><pre class='md-fences mock-cm' style='display:block;position:relative'>ngOnInit() {
    //获取动态参数id
    const contactId = this.route.snapshot.params.id
    //发起请求
    this.http.get(`http://localhost:3000/contacts/${contactId}`)
    .toPromise()
    .then(data=&gt;{
      console.log(data)
      this.fromData = data
    }).catch(err=&gt;{
      console.log(err)
    })
  }</pre><p>4、编辑联系人</p><pre class='md-fences mock-cm' style='display:block;position:relative'>updataContact(){
    const id = this.fromData.id
    this.http.patch(`http://localhost:3000/contacts/${id}`,this.fromData)
    .toPromise()
    .then(data=&gt;{
      console.log(data)
      this.router.navigate([&quot;/comtact&quot;])  //跳转到联系人列表
      
    }).catch(err=&gt;{
      console.log(err)
    })
  }</pre><p></p></div>
</body>
</html>